Skip to content

Repository files navigation

باشگاه من — وب‌اپلیکیشن تمرین بدنسازی

وب‌اپلیکیشنی برای مدیریت تمرین بدنسازی، با رابط کاربری کاملاً فارسی و راست‌به‌چپ (RTL)؛ شامل برنامه‌ساز خودکار تمرین، بانک حرکات جست‌وجوپذیر و پیگیری پیشرفت با نمودار.

پشتهٔ فناوری (Tech Stack)

لایهفناوری
فرانت‌اندReact 18، Vite، React Router، TanStack Query، React Hook Form، Recharts، Tailwind CSS v4
بک‌اندNode.js، Express 4، Mongoose
پایگاه‌دادهMongoDB (میزبانی‌شدهٔ اختصاصی)
احراز هویتJWT (Authorization: Bearer <token>)، bcrypt

سراسر پروژه با جاوااسکریپت خالص نوشته شده و از TypeScript استفاده نمی‌کند.

این سند در پنج بخش سازمان‌دهی شده است:

  1. معماری سیستم
  2. ساختار پایگاه‌داده
  3. مستندات API
  4. فایل‌های طراحی UI/UX و نسخهٔ پیاده‌سازی‌شده
  5. دستورالعمل نصب و راه‌اندازی سرور و محیط ابری

بخش ۱ — معماری سیستم

پروژه یک مونوریپو (monorepo) با دو اپلیکیشن مستقل است که با npm workspaces مدیریت می‌شود:

مرورگر ──HTTP──▶ سرور توسعهٔ Vite (پورت 5173) ──proxy /api──▶ Express (پورت 5000) ──▶ MongoDB (پورت 27017)
│ (سرو React) REST JSON Mongoose
└── localStorage: توکن JWT
  • کلاینت (client) یک اپلیکیشن تک‌صفحه‌ای (SPA) مبتنی بر React است. هرگز مستقیم به پایگاه‌داده دسترسی ندارد و فقط از طریق API با سرور ارتباط برقرار می‌کند.
  • سرور (server) یک REST API بدون حالت (stateless) است. تمام اعتبارسنجی، احراز هویت و دسترسی به پایگاه‌داده منحصراً روی سرور انجام می‌شود.
  • وضعیت برنامه در دو جا نگه‌داری می‌شود: توکن JWT در localStorage مرورگر (برای شناسایی کاربر) و MongoDB (برای همهٔ داده‌های دیگر).

دلیل اهمیت این جداسازی این است که سرور تنها بخشی از سیستم است که به هیچ ورودی از سمت کلاینت اعتماد نمی‌کند؛ چون کلاینت را هرکسی می‌تواند تغییر دهد. هش کردن رمز عبور، اعتبارسنجی ورودی و محدودسازی مالکیت داده، همگی فقط در سرور پیاده‌سازی شده‌اند.

ساختار پوشه‌ها

bodybuilding/
├── client/ فرانت‌اند React
│ └── src/
│ ├── api/ نمونهٔ axios به‌همراه یک ماژول برای هر منبع داده
│ ├── components/ کامپوننت‌های چیدمان، رابط کاربری مشترک، نمودارها
│ ├── context/ AuthContext — نگه‌داری توکن و اعتبارسنجی نشست
│ ├── pages/ یک کامپوننت به‌ازای هر مسیر (route)
│ ├── constants/ برچسب‌های فارسی برای مقادیر enum سمت سرور
│ └── utils/ تاریخ جلالی، اعداد فارسی، جاسازی ویدیو
└── server/ API با Express
└── src/
├── models/ مدل‌های User، Exercise، WorkoutProgram، ProgressLog
├── controllers/ هندلرهای درخواست (منطق تجاری)
├── routes/ تعریف مسیرها به‌همراه قوانین express-validator
├── services/ منطق تولید برنامهٔ تمرینی
├── middleware/ احراز هویت، اعتبارسنجی، مدیریت خطا
└── seed/ دادهٔ اولیهٔ بانک حرکات

ترتیب میان‌افزارها (middleware) در server/src/app.js

ترتیب اجرای میان‌افزارها اهمیت دارد؛ هر لایه به لایه‌های پیش از خودش وابسته است:

  1. helmet() — افزودن هدرهای امنیتی به هر پاسخ
  2. cors() — مجاز کردن origin مرورگر
  3. express.json() — پردازش بدنهٔ درخواست
  4. express-mongo-sanitize() — حذف عملگرهای $ از ورودی، بلافاصله بعد از پارس شدن و پیش از رسیدن به هر هندلر
  5. morgan() — لاگ‌گیری (فقط در محیط توسعه)
  6. مسیرهای /api/health، /api/auth، /api/exercises، /api/programs، /api/progress
  7. notFound — بازگرداندن کد ۴۰۴ برای مسیرهای نامشخص
  8. errorHandler — تبدیل هر خطا به یک پاسخ JSON یکدست

برای جزئیات کامل‌تر معماری، جریان گام‌به‌گام درخواست‌ها و سیستم طراحی، به فایل ARCHITECTURE.md مراجعه کنید.


بخش ۲ — ساختار پایگاه‌داده

پایگاه‌داده از نوع MongoDB (سندمحور و بدون نیاز به شِمای رابطه‌ای ثابت) است و در سمت سرور با Mongoose مدل‌سازی می‌شود. به همین دلیل، فایل SQL یا دیاگرام رابطه‌ای (ER) جداگانه‌ای در پروژه وجود ندارد؛ ساختار داده مستقیماً در فایل‌های زیر تعریف شده است:

مدلفایلتوضیح
کاربر (User)server/src/models/User.jsحساب کاربری، رمز عبور هش‌شده، پروفایل تمرینی
حرکت (Exercise)server/src/models/Exercise.jsبانک حرکات؛ دادهٔ مرجع مشترک بین همهٔ کاربران
برنامهٔ تمرینی (WorkoutProgram)server/src/models/WorkoutProgram.jsبرنامهٔ هفتگی هر کاربر
لاگ پیشرفت (ProgressLog)server/src/models/ProgressLog.jsثبت وزنه، تکرار و مدت‌زمان هر ست تمرینی

جزئیات هر مدل

User

  • فیلدهای name، email (یکتا)، و password (هش‌شده با bcrypt؛ با select: false تا در پاسخ‌های عادی API بازگردانده نشود)
  • role: نقش کاربر، با مقدار پیش‌فرض user
  • profile: جنسیت، سال تولد، قد، وزن، سطح تمرینی و هدف

رمز عبور در یک هوک pre('save') به‌طور خودکار هش می‌شود؛ در نتیجه هیچ کنترلری امکان ذخیرهٔ رمز عبور به‌صورت متن ساده را ندارد، حتی در کدهای آینده.

Exercise

  • فیلدهای name (فارسی)، nameEn، description و videoUrl
  • muscleGroup، equipment و difficulty: هرکدام محدود به مقادیر ثابتی که در server/src/constants/enums.js تعریف شده‌اند
  • یک ایندکس ترکیبی روی { muscleGroup, equipment, difficulty } برای جست‌وجوی سریع‌تر

WorkoutProgram

  • ارجاع (reference) به user، یعنی مالک برنامه
  • days: آرایه‌ای از روزهای تمرین که به‌صورت جاسازی‌شده (embedded) ذخیره می‌شوند
  • هر روز شامل آرایه‌ای از حرکات است؛ هر حرکت با یک ObjectId به سند Exercise ارجاع داده می‌شود، در حالی‌که مقادیر sets، reps و restSeconds مخصوص همان برنامه هستند
  • isActive: در هر لحظه فقط یک برنامه برای هر کاربر فعال است؛ تولید برنامهٔ جدید، برنامهٔ قبلی را غیرفعال می‌کند نه حذف — تا تاریخچه حفظ شود

ProgressLog

  • ارجاع به user و exercise
  • sets: آرایه‌ای از ست‌های ثبت‌شده، شامل weightKg، reps و durationSeconds
  • ایندکس ترکیبی روی { user, exercise, date } که مستقیماً به کوئری‌های نمودار پیشرفت سرعت می‌بخشد

نکته: تاریخ‌ها همیشه در پایگاه‌داده به‌صورت میلادی (ISO) و اعداد همیشه به‌صورت لاتین ذخیره می‌شوند. تبدیل به تاریخ جلالی و اعداد فارسی فقط در لایهٔ نمایش، در فایل client/src/utils/format.js، انجام می‌شود؛ همین موضوع باعث می‌شود مرتب‌سازی و کوئری‌های بازه‌ای تاریخ همیشه درست کار کنند.


بخش ۳ — مستندات API

مسیر پایهٔ همهٔ درخواست‌ها /api است. مسیرهای محافظت‌شده به هدر Authorization: Bearer <token> نیاز دارند.

احراز هویت (Auth)

متدمسیرنیاز به توکنبدنه / پارامتر
POST/auth/register{ name, email, password }{ user, token }
POST/auth/login{ email, password }{ user, token }
GET/auth/meاطلاعات کاربر جاری
PUT/auth/me{ name?, profile? }
PUT/auth/change-password{ currentPassword, newPassword }

حرکات (Exercises)

متدمسیرنیاز به توکنبدنه / پارامتر
GET/exercises?search=&muscleGroup=&equipment=&difficulty=&page=&limit=
GET/exercises/:idیک حرکت مشخص

برنامه‌های تمرینی (Programs)

متدمسیرنیاز به توکنبدنه / پارامتر
POST/programs/generate{ level, goal, daysPerWeek } — ساخت و فعال‌سازی خودکار برنامه
POST/programs{ title?, level, goal, daysPerWeek } — برنامهٔ خالی برای تکمیل دستی
GET/programsهمهٔ برنامه‌های کاربر
GET/programs/activeبرنامهٔ فعال، یا null
GET/programs/:idیک برنامهٔ مشخص
PUT/programs/:id{ title?, description?, level?, goal?, days? }
PUT/programs/:id/activateفعال‌سازی این برنامه
DELETE/programs/:idحذف برنامه

پیشرفت (Progress)

متدمسیرنیاز به توکنبدنه / پارامتر
POST/progress{ exercise, date?, sets[], notes? }
GET/progress?exercise=&from=&to=&page=&limit=
GET/progress/stats?exercise=&from=&to=[{ date, maxWeight, totalReps, totalSets, totalDurationSeconds, volume }]
GET/progress/exercisesحرکاتی که کاربر برایشان لاگ ثبت کرده (برای انتخابگر نمودار)
GET/progress/:idیک رکورد مشخص
PUT/progress/:idویرایش یک رکورد
DELETE/progress/:idحذف یک رکورد

قالب خطاها

خطاها به شکل { message, errors?: [{ field, message }] } بازگردانده می‌شوند. برای رکوردهایی که متعلق به کاربر دیگری هستند، پاسخ 404 بازگردانده می‌شود، نه 403؛ به این ترتیب وجود یا عدم‌وجود رکورد برای کاربر دیگر فاش نمی‌شود.

نکته: مستندات تعاملی به‌شکل OpenAPI یا Swagger هنوز برای پروژه تولید نشده و در فهرست کارهای آتی قرار دارد.


بخش ۴ — فایل‌های طراحی UI/UX و نسخهٔ پیاده‌سازی‌شده

این پروژه فاقد فایل طراحی مجزا (مانند Figma یا Sketch) است؛ سیستم طراحی مستقیماً در کد پیاده‌سازی شده و همان کد، منبع حقیقت واحد (single source of truth) طراحی به‌شمار می‌رود.

سیستم طراحی

تعریف‌شده در فایل client/src/index.css به‌صورت متغیرهای سراسری CSS:

  • رنگ: سه طیف رنگی — ink (خنثی؛ برای متن و سطوح)، flame (اصلی؛ برای دکمه‌ها و حالت فعال) و volt (تأکیدی؛ برای پیشرفت و پیام موفقیت)
  • کنتراست: تمام رنگ‌های متن در برابر پس‌زمینه، مطابق استاندارد WCAG AA (حداقل نسبت ۴.۵ به ۱) بررسی و تأیید شده‌اند
  • راست‌به‌چپ (RTL): با سه مکانیزم پیاده‌سازی شده است — ویژگی dir="rtl" روی تگ <html>، استفاده از خواص منطقی CSS (مانند ps-*، me-*، text-start) به‌جای خواص جهتی ثابت، و کلاس‌های rtl: برای موارد استثنا مثل فلش برگشت
  • نمودارها: به‌طور عمدی درون یک ظرف (container) با dir="ltr" رندر می‌شوند، چون نمودارهای زمانی در همهٔ زبان‌ها به‌طور متعارف از چپ به راست خوانده می‌شوند
  • انیمیشن: بین ۱۵۰ تا ۳۰۰ میلی‌ثانیه، فقط روی transform و opacity، و با پشتیبانی کامل از تنظیمات prefers-reduced-motion
  • آیکون‌ها: یک مجموعهٔ واحد و درون‌خطی (inline SVG) با حدود ۳۵ آیکون؛ بدون استفاده از هیچ ایموجی، چون ایموجی در پلتفرم‌های مختلف ظاهر متفاوتی دارد

فایل‌های کلیدی رابط کاربری

بخشمسیر
توکن‌های طراحی (رنگ، سایه، انیمیشن)client/src/index.css
مجموعهٔ آیکون‌هاclient/src/components/Icon.jsx
کامپوننت‌های پایهٔ مشترک (دکمه، ورودی، کارت و…)client/src/components/common/index.jsx
چیدمان صفحات ورود و ثبت‌نامclient/src/components/layout/AuthLayout.jsx
چیدمان صفحات داخل برنامهclient/src/components/layout/AppLayout.jsx
نمودارهای پیشرفتclient/src/components/charts/ProgressCharts.jsx
ورودی تاریخ جلالیclient/src/components/JalaliDateInput.jsx

صفحات پیاده‌سازی‌شده (نسخهٔ اجراشده)

هر صفحه یک کامپوننت مستقل در پوشهٔ client/src/pages/ است:

صفحهفایل
ورودLoginPage.jsx
ثبت‌نامRegisterPage.jsx
خانهHomePage.jsx
داشبوردDashboardPage.jsx
بانک حرکاتExercisesListPage.jsx
جزئیات حرکتExerciseDetailPage.jsx
برنامه‌ساز خودکارProgramGeneratorPage.jsx
ویرایش دستی برنامهProgramBuilderPage.jsx
نمایش برنامهProgramViewPage.jsx
ثبت پیشرفتProgressLogPage.jsx
نمودار پیشرفتProgressChartsPage.jsx
پروفایل کاربرProfilePage.jsx
صفحهٔ خطای ۴۰۴NotFoundPage.jsx

برای مشاهدهٔ نسخهٔ زندهٔ رابط کاربری، پروژه را طبق بخش ۵ اجرا کنید و آدرس http://localhost:5173 را در مرورگر باز کنید.


بخش ۵ — دستورالعمل نصب و راه‌اندازی سرور و محیط ابری

پیش‌نیازها

  • Node.js نسخهٔ ۱۸ به بالا
  • MongoDB (نصب محلی یا سرویس ابری)

نصب و اجرای محلی (Development)

۱. نصب وابستگی‌ها (یک دستور، هر دو workspace را نصب می‌کند):

npm install

۲. نصب MongoDB Community Server

نصب‌کنندهٔ ویندوز را دانلود و اجرا کنید و گزینهٔ «Install MongoDB as a Service» را انتخاب کنید تا سرویس همراه با ویندوز به‌طور خودکار اجرا شود. پورت پیش‌فرض 27017 است.

نکته برای کاربران ایران: آدرس CDN اصلی MongoDB، یعنی fastdl.mongodb.org، از آی‌پی‌های ایران خطای 403 Forbidden بازمی‌گرداند و همین موضوع باعث شکست دستور winget install MongoDB.Server نیز می‌شود. آدرس مبدأ downloads.mongodb.org همان فایل رسمی را سرو می‌کند و در دسترس است:

curl.exe-L -o mongodb.msi https://downloads.mongodb.org/windows/mongodb-windows-x86_64-8.3.8-signed.msi
(Get-FileHash mongodb.msi -Algorithm SHA256).Hash

هش دریافتی را با چک‌سام منتشرشده در همان آدرس (با پسوند .sha256) مقایسه کنید.

استفاده از MongoDB Atlas از ایران ممکن نیست، چون این سرویس در آمریکا میزبانی می‌شود و مشمول تحریم است؛ حساب‌های ساخته‌شده از آی‌پی ایران مسدود یا بسته می‌شوند. راه‌حل، میزبانی نسخهٔ متن‌باز خودِ MongoDB است، همان‌طور که در بالا توضیح داده شد. برای استقرار روی سرور، ارائه‌دهنده‌های ایرانی مانند لیارا (Liara) یا آروان‌کلاود (ArvanCloud) سرویس MongoDB مدیریت‌شده و میزبانی وب ارائه می‌دهند.

بررسی اجرا بودن سرویس:

Get-Service MongoDB

۳. تنظیم سرور

فایل server/.env.example را به server/.env کپی و مقداردهی کنید:

PORT=5000
NODE_ENV=development
MONGO_URI=mongodb://127.0.0.1:27017/bodybuilding
JWT_SECRET=<یک رشتهٔ تصادفی و طولانی>
JWT_EXPIRES_IN=7d
CLIENT_ORIGIN=http://localhost:5173

بخش /bodybuilding در انتهای آدرس، نام پایگاه‌داده است و در اولین نوشتن به‌طور خودکار ساخته می‌شود؛ نیازی به آماده‌سازی دستی نیست. برای تولید یک JWT_SECRET قوی:

node -e "console.log(require('crypto').randomBytes(48).toString('hex'))"

کلاینت برای توسعهٔ محلی به هیچ تنظیماتی نیاز ندارد — Vite مسیرهای /api را به‌طور خودکار به پورت ۵۰۰۰ پروکسی می‌کند. فایل client/.env.example نیز برای زمانی که دو نیمهٔ پروژه روی دو origin جداگانه مستقر شوند، آماده شده است.

۴. بارگذاری بانک حرکات اولیه

npm run seed

این دستور ۲۰ حرکت را وارد پایگاه‌داده می‌کند و فقط مجموعهٔ exercises را دست‌کاری می‌کند؛ کاربران، برنامه‌ها و لاگ‌های پیشرفت هرگز تغییر نمی‌کنند، بنابراین اجرای دوبارهٔ آن کاملاً بی‌خطر است.

۵. اجرای همزمان کلاینت و سرور

npm run dev
  • فرانت‌اند: http://localhost:5173
  • API: http://localhost:5000

دستورات موجود

دستورکاربرد
npm run devاجرای همزمان API و فرانت‌اند
npm run dev:serverفقط اجرای API (با nodemon)
npm run dev:clientفقط اجرای فرانت‌اند
npm run seedبازسازی بانک حرکات
npm run buildساخت نسخهٔ نهایی فرانت‌اند در پوشهٔ client/dist

استقرار با Docker

پروژه شامل فایل‌های آمادهٔ Docker است:

فایلکاربرد
Dockerfileساخت یک ایمیج واحد شامل کلاینت و سرور
docker-compose.ymlاجرای محیط توسعه (کلاینت، سرور، MongoDB)
docker-compose.prod.ymlاجرای محیط عملیاتی (اپلیکیشن، MongoDB، Nginx)
nginx.confتنظیمات reverse proxy و گواهی SSL

اجرای محلی برای آزمایش پیش از استقرار:

docker-compose up -d
docker-compose logs -f

توقف سرویس‌ها:

docker-compose down

مراحل کامل استقرار روی سرور — شامل نصب Docker، آپلود پروژه، تنظیم متغیرهای محیطی و اجرای نسخهٔ عملیاتی — در فایل DOCKER_DEPLOYMENT.md شرح داده شده است. راهنمای اختصاصی استقرار روی میزبان‌های ایرانی نیز در فایل DEPLOY_IRAN.md آمده، و برای یک شروع سریع‌تر با Docker می‌توانید فایل QUICKSTART_DOCKER.md را ببینید.


پیوست — موارد خارج از محدودهٔ نسخهٔ فعلی

این موارد به‌طور آگاهانه از ساخت اولیه کنار گذاشته شده‌اند و فاز طبیعی بعدی پروژه به‌شمار می‌روند:

  • پنل مدیریت برای مدیریت حرکات و کاربران (فیلد role از پیش در مدل User وجود دارد)
  • اعلان‌های ایمیل یا پیامک و یادآوری جلسات تمرینی
  • مستندات تعاملی OpenAPI / Swagger
  • تست‌های خودکار واحد و یکپارچگی
  • پایپ‌لاین CI/CD و پیکربندی استقرار خودکار

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages