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