BikeControl (SwiftControl)
使用 Zwift Click、Zwift Play、Shimano Di2 或任何藍牙控制器,搭配 MyWhoosh、Rouvy、Zwift 等。iOS、Android、Windows、macOS 均可免費試用。
AI 翻译
尚未检测到更新。GitHub 发布版本后会显示在这里。
个人 GitHub 账号下公开仓库的所有者可以登录并验证所有权,自行管理介绍,无需管理员批准。
登录并生成验证文件,在 30 分钟内将其提交到此仓库的默认分支。其他分支或分叉仓库中的文件无效。然后在下方检查文件,即可无需管理员批准直接管理项目。请保留文件以维持管理权限。
如需登录,将前往登录页面。登录后请回到此处,再次点击所选的验证按钮。
在项目文件夹中运行 /nomorevibe verify,即可验证所有权并自行管理介绍。
一分钟完成验证制作者的介绍仅有上面的一句话。 更多详情请阅读仓库 README。 仓库 README ↗
正在加载完整 README。
查看完整 README ↗One platform, two products: Club2Coach (clubs ↔ coaches) and Coach2Mentor (coaches ↔ mentors). One login covers both — but every role you activate (Club2Coach coach, Club2Coach club, Coach2Mentor coach, Coach2Mentor mentor) is paid for separately.
This replaces the earlier club2coach project entirely. That was a
single-product, browse-and-swipe prototype. This is a full rebuild
around your actual Club2Coach and Coach2Mentor designs: private
admin-curated listings for Club2Coach, browsable mentor profiles for
Coach2Mentor, weighted match scoring for both, and a shared identity
with per-role payment gating. Don't try to merge the old project with
this one — start fresh from this folder.
people — one row per login: name, mobile, email, gender,
region, current licence. Shared across both products.club2coach_coach_listings,
club2coach_club_vacancies, coach2mentor_coach_listings,
coach2mentor_mentor_listings. Each has its own paid flag. Paying
for one never unlocks another, even for the same person./club2coach/admin and choose
which to share — that's what club2coach_shares records.people.mobile and
people.email are never broadly readable. A coach only gains access
to a mentor's actual contact record once that mentor accepts their
request (see the RLS policy comments in schema.sql). Club2Coach
works the same way via club2coach_shares.In the SQL Editor, paste and run supabase/schema.sql in full. It sets
up every table, the scoring-support indexes, and Row Level Security —
including the admin PIN functions.
Still in the SQL Editor, run (replacing with your actual 6-digit PIN):
select set_admin_pin('123456');
This is the one PIN that unlocks /club2coach/admin and
/coach2mentor/admin — shared across both products, tied to whichever
logged-in person enters it correctly (see grant_admin_pin_session in
the schema for exactly how). You can change it later from the same SQL
editor using select change_admin_pin('old', 'new');, or add that as
an in-app admin settings screen later.
Copy .env.example to .env.local, fill in your Supabase Project URL
and anon/publishable key.
npm install
npm run dev
Push to GitHub, import into Vercel, add the same two environment variables there.
Every listing has a paid boolean that gates whether it's included in
matching (Club2Coach) or browsable (Coach2Mentor mentor listings). Right
now, marking something paid is a manual admin action — you click
"Mark paid" in the admin panel after receiving payment however you're
currently collecting it (bank transfer, in person, whatever). This
calls one of four mark_*_paid database functions, which is admin-only
by RLS (checked server-side, not just hidden in the UI).
This is deliberate for now, matching what we discussed: no live Stripe
integration until there's real demand. When you're ready for real
payment collection, the architecture is ready for it — each price
already lives as a constant in lib/constants.ts
(ROLE_PRICES_AUD), and swapping "manual mark as paid" for "Stripe
Checkout marks it paid via webhook" is a contained change, not a
rebuild.
lib/scoring.ts has the two scoring functions:
scoreClub2CoachMatch — accreditation, ability, competition level,
age group, geography, salary, gender — each weighted per your
sliders in /club2coach/admin.scoreCoach2MentorMatch — specialism overlap, career stage,
geography, availability, budget fit, gender — weighted via
/coach2mentor/admin.One honest limitation worth knowing: the "gender" sub-score in both
functions compares stated preferences, not verified actual gender —
because actual gender lives in the private people table, which isn't
broadly readable (by design, to protect contact info sitting in that
same table). If you want a truer gender match later, the clean fix is
adding a denormalised gender column directly on each listing table
(low sensitivity, unlike mobile/email) rather than loosening people
access.
lib/constants.ts holds every dropdown list — regions, competition
levels, accreditation ladder, specialisms — keyed by state
(REGIONS_BY_STATE, COMPETITION_LEVELS_BY_STATE), which the forms
already read from a single source. Some states have a fuller ladder
than others; bringing a state's list up to date, or adding a new one,
is a constants-file and form-dropdown change, not a schema rewrite.