docs: update README with project overview, features, and setup instructions
This commit is contained in:
@@ -1,104 +1,894 @@
|
||||
# نوبت 724 (Nobat724)
|
||||
# 🏥 نوبت724 (Nobat724) - سیستم نوبتدهی آنلاین پزشکی
|
||||
|
||||
**نوبت 724** is an appointment booking platform built using **Next.js** and **React**. This project is designed to facilitate appointment scheduling—especially for clinics and healthcare providers—with support for Persian calendar, maps, responsive UI components, and beautiful animations.
|
||||
## 📋 فهرست مطالب
|
||||
|
||||
## 🚀 Tech Stack
|
||||
|
||||
- **Framework:** Next.js
|
||||
- **Language:** JavaScript / React
|
||||
- **UI Libraries:** MUI (Material-UI), Styled-Components, Emotion
|
||||
- **Date Handling:** Day.js, Date-fns, Jalali-Moment
|
||||
- **Calendar:** Jalaali React Date Picker
|
||||
- **Maps:** MapTiler SDK, Google Map Picker
|
||||
- **Forms & Uploads:** React Toastify, React Images Uploading
|
||||
- **Animations:** AOS (Animate on Scroll)
|
||||
- **Charts & Pickers:** @mui/x-charts, @mui/x-date-pickers
|
||||
- **Styling:** Tailwind CSS, Emotion, Styled-Components
|
||||
- **RTL Support:** Stylis Plugin RTL
|
||||
|
||||
## 📦 Installation
|
||||
|
||||
```bash
|
||||
# Clone the repo
|
||||
git clone https://github.com/your-username/nobat724.git
|
||||
cd nobat724
|
||||
|
||||
# Install dependencies
|
||||
npm install
|
||||
```
|
||||
|
||||
## 🛠 Available Scripts
|
||||
|
||||
```bash
|
||||
npm run dev
|
||||
```
|
||||
|
||||
Runs the app in development mode. Open [http://localhost:3000](http://localhost:3000) to view it in the browser.
|
||||
|
||||
```bash
|
||||
npm run build
|
||||
```
|
||||
|
||||
Builds the app for production.
|
||||
|
||||
```bash
|
||||
npm start
|
||||
```
|
||||
|
||||
Starts the production server after building.
|
||||
|
||||
```bash
|
||||
npm run lint
|
||||
```
|
||||
|
||||
Checks the code for linting issues.
|
||||
|
||||
## ⚙️ Environment Variables
|
||||
|
||||
Create a `.env.local` file in the root directory with the following variables:
|
||||
|
||||
```
|
||||
NEXT_PUBLIC_API_URL=https://back-dev.clinic-pro.ir
|
||||
NEXT_PUBLIC_CLIENT_ID=NWuujdYHjtAtrhrk_zoWB3w0kyf56wRCOaY36MIqvbs
|
||||
NEXT_PUBLIC_CLIENT_SECRET=trhrk_zoWB3w0kyf
|
||||
NODE_ENV=development # or production
|
||||
```
|
||||
|
||||
**Note:** In Next.js, environment variables that need to be accessible in the browser must be prefixed with `NEXT_PUBLIC_`. Variables without this prefix are only available on the server side.
|
||||
|
||||
## 🌐 Features
|
||||
|
||||
- ✅ Responsive design using MUI and Tailwind
|
||||
- 🗕 Persian (Jalali) date picker
|
||||
- 🟠 Map location picker with MapTiler and Google Maps
|
||||
- 🔒 Cookie management with `universal-cookie`
|
||||
- 📸 Image uploading support
|
||||
- 🌙 Dark mode support using `next-themes`
|
||||
- 🌍 Right-to-left (RTL) support for Persian language
|
||||
|
||||
## 📁 Project Structure
|
||||
|
||||
```
|
||||
nobat724/
|
||||
├── pages/ # Next.js pages
|
||||
├── components/ # React components
|
||||
├── styles/ # Global styles and Tailwind config
|
||||
├── public/ # Static assets
|
||||
├── utils/ # Utility functions
|
||||
└── ...
|
||||
```
|
||||
|
||||
## 🗕 Roadmap
|
||||
|
||||
- [ ] Multi-language support
|
||||
- [ ] Admin panel for managing appointments
|
||||
- [ ] Role-based access
|
||||
- [ ] Notifications and reminders
|
||||
|
||||
## 📜 License
|
||||
|
||||
This project is private or under your preferred license.
|
||||
- [معرفی پروژه](#معرفی-پروژه)
|
||||
- [معماری و تکنولوژی](#معماری-و-تکنولوژی)
|
||||
- [ساختار پروژه](#ساختار-پروژه)
|
||||
- [ویژگیهای کلیدی](#ویژگیهای-کلیدی)
|
||||
- [راهاندازی پروژه](#راهاندازی-پروژه)
|
||||
- [سیستم Multi-Domain](#سیستم-multi-domain)
|
||||
- [احراز هویت و مجوزها](#احراز-هویت-و-مجوزها)
|
||||
- [مسیرها و صفحات](#مسیرها-و-صفحات)
|
||||
- [کامپوننتهای اصلی](#کامپوننتهای-اصلی)
|
||||
- [API و سرویسها](#api-و-سرویسها)
|
||||
- [Deployment](#deployment)
|
||||
|
||||
---
|
||||
|
||||
> Developed with ❤️ by the Nobat724 team.
|
||||
## 🎯 معرفی پروژه
|
||||
|
||||
**نوبت724** یک پلتفرم جامع و پیشرفته برای نوبتدهی آنلاین پزشکی است که امکان رزرو نوبت از پزشکان و کلینیکها را به صورت آنلاین فراهم میکند.
|
||||
|
||||
### ویژگیهای اصلی:
|
||||
|
||||
- ✅ **Multi-Domain Architecture**: پشتیبانی از دامنههای مختلف برای شهرهای مختلف
|
||||
- ✅ **رزرو نوبت آنلاین**: سیستم کامل رزرو نوبت با تقویم شمسی
|
||||
- ✅ **پنل مدیریتی**: پنل کامل برای نمایندگان و پزشکان
|
||||
- ✅ **احراز هویت**: سیستم ورود و احراز هویت با OTP
|
||||
- ✅ **پرداخت آنلاین**: سیستم پرداخت یکپارچه
|
||||
- ✅ **Responsive Design**: طراحی کاملاً واکنشگرا با Tailwind CSS
|
||||
- ✅ **Dark Mode**: پشتیبانی کامل از حالت تاریک
|
||||
- ✅ **SEO Optimized**: بهینهسازی کامل SEO با متادیتای داینامیک
|
||||
|
||||
---
|
||||
|
||||
## 🏗️ معماری و تکنولوژی
|
||||
|
||||
### Frontend Framework
|
||||
|
||||
- **Next.js 14.2.20** (App Router)
|
||||
- **React 18**
|
||||
- **Server Components** و **Client Components**
|
||||
|
||||
### UI/UX
|
||||
|
||||
- **Material-UI (MUI) v7**: کامپوننتهای UI
|
||||
- **Tailwind CSS 3.4**: استایلدهی
|
||||
- **Emotion**: CSS-in-JS
|
||||
- **Dark Mode**: با `next-themes`
|
||||
- **Responsive Design**: Mobile-first approach
|
||||
|
||||
### State Management & Data Fetching
|
||||
|
||||
- **React Context API**: مدیریت state سراسری
|
||||
- **Axios**: درخواستهای HTTP
|
||||
- **Server-Side Rendering (SSR)**
|
||||
|
||||
### Authentication & Authorization
|
||||
|
||||
- **CASL**: مدیریت دسترسیها
|
||||
- **JWT Tokens**: احراز هویت
|
||||
- **Cookie-based Auth**: ذخیره توکنها
|
||||
|
||||
### کتابخانههای تخصصی
|
||||
|
||||
- **jalali-moment & moment-jalaali**: تبدیل تاریخ شمسی
|
||||
- **jalaali-react-date-picker**: Date Picker فارسی
|
||||
- **react-toastify**: نوتیفیکیشنها
|
||||
- **html2canvas & jspdf**: تولید PDF
|
||||
- **qrcode.react**: تولید QR Code
|
||||
- **@maptiler/sdk**: نمایش نقشه
|
||||
|
||||
### Development Tools
|
||||
|
||||
- **Docker & Docker Compose**: Containerization
|
||||
- **ESLint**: Code Quality
|
||||
- **Prettier**: Code Formatting
|
||||
|
||||
---
|
||||
|
||||
## 📁 ساختار پروژه
|
||||
|
||||
```
|
||||
nobat724_front/
|
||||
├── app/ # Next.js App Directory
|
||||
│ ├── layout.js # Root Layout با Metadata داینامیک
|
||||
│ ├── page.js # صفحه اصلی
|
||||
│ ├── globals.css # استایلهای سراسری
|
||||
│ ├── about-us/ # درباره ما
|
||||
│ ├── appointment/[doctorId]/ # صفحه رزرو نوبت (Dynamic Route)
|
||||
│ ├── blog/[slug]/ # صفحه جزئیات بلاگ
|
||||
│ ├── blogs/ # لیست بلاگها
|
||||
│ ├── clinic/[slug]/ # صفحه جزئیات کلینیک
|
||||
│ ├── clinics/ # لیست کلینیکها
|
||||
│ ├── contact-us/ # تماس با ما
|
||||
│ ├── dashboard/ # داشبورد عمومی
|
||||
│ ├── doctor/[slug]/ # صفحه جزئیات پزشک
|
||||
│ ├── doctors/ # لیست پزشکان
|
||||
│ ├── login/ # ورود
|
||||
│ ├── login-verify/ # تایید OTP
|
||||
│ ├── panel/(layout)/ # پنل مدیریتی (Route Group)
|
||||
│ │ ├── dashboard/ # داشبورد پنل
|
||||
│ │ ├── user-account/ # حساب کاربری
|
||||
│ │ ├── add-doctor/ # افزودن پزشک
|
||||
│ │ └── turns/ # مدیریت نوبتها
|
||||
│ ├── specialties/ # تخصصهای پزشکی
|
||||
│ └── component/ # کامپوننتهای مشترک App
|
||||
│
|
||||
├── components/ # کامپوننتهای اصلی
|
||||
│ ├── home/ # کامپوننتهای صفحه اصلی
|
||||
│ ├── appointment/ # کامپوننتهای رزرو نوبت
|
||||
│ ├── doctor/ # کامپوننتهای پزشک
|
||||
│ ├── doctors/ # کامپوننتهای لیست پزشکان
|
||||
│ ├── clinic/ # کامپوننتهای کلینیک
|
||||
│ ├── clinics/ # کامپوننتهای لیست کلینیکها
|
||||
│ ├── panel/ # کامپوننتهای پنل
|
||||
│ ├── layout/ # Layout کامپوننتها
|
||||
│ ├── layoutPanel/ # Layout پنل
|
||||
│ ├── register/ # ثبتنام و ورود
|
||||
│ └── icons/ # آیکونهای سفارشی
|
||||
│
|
||||
├── lib/ # کتابخانهها و Utilities
|
||||
│ ├── ability.js # تعریف دسترسیها (CASL)
|
||||
│ ├── auth.js # احراز هویت
|
||||
│ ├── getStateInfo.js # دریافت اطلاعات استان/شهر (Server)
|
||||
│ ├── getStateInfoClient.js # دریافت اطلاعات استان/شهر (Client)
|
||||
│ ├── getCanonicalUrl.js # تولید Canonical URL
|
||||
│ └── req.js # Helper برای Fetch
|
||||
│
|
||||
├── services/ # سرویسهای API
|
||||
│ ├── api.js # تنظیمات Axios
|
||||
│ ├── response.js # API Endpoints
|
||||
│ └── clinicApi.js # APIهای مربوط به کلینیک
|
||||
│
|
||||
├── context/ # React Context
|
||||
│ └── ProvinceProvider.js # Context استان/شهر
|
||||
│
|
||||
├── data/ # فایلهای JSON استاتیک
|
||||
│ ├── city.json # اطلاعات شهرها (Multi-Domain)
|
||||
│ ├── state.json # اطلاعات استانها
|
||||
│ ├── specialties.json # تخصصهای پزشکی
|
||||
│ ├── doctors.json # Mock Data پزشکان
|
||||
│ └── clinics.json # Mock Data کلینیکها
|
||||
│
|
||||
├── helper/ # توابع کمکی
|
||||
│ └── index.js # Utility Functions
|
||||
│
|
||||
├── utils/ # Utilities
|
||||
│ └── index.js # توابع کمکی (removeToken و...)
|
||||
│
|
||||
├── hooks/ # Custom Hooks
|
||||
│ └── useCanonicalUrl.js # Hook برای Canonical URL
|
||||
│
|
||||
├── mui/ # تنظیمات MUI
|
||||
│ └── index.js # Theme Configuration
|
||||
│
|
||||
├── public/ # فایلهای استاتیک
|
||||
│ ├── assets/ # تصاویر و آیکونها
|
||||
│ └── fonts/ # فونتها
|
||||
│
|
||||
├── middleware.js # Next.js Middleware
|
||||
├── next.config.js # تنظیمات Next.js
|
||||
├── tailwind.config.js # تنظیمات Tailwind
|
||||
├── docker-compose.yml # Docker Compose
|
||||
├── dockerfile # Dockerfile
|
||||
└── package.json # Dependencies
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ✨ ویژگیهای کلیدی
|
||||
|
||||
### 1. Multi-Domain Architecture
|
||||
|
||||
پروژه از **معماری Multi-Domain** پشتیبانی میکند که به هر شهر اجازه میدهد دامنه مستقل خود را داشته باشد:
|
||||
|
||||
```javascript
|
||||
// در data/city.json
|
||||
{
|
||||
"id": "600",
|
||||
"domain": "nobat724.com", // دامنه اصلی
|
||||
"site_name": "نوبت724",
|
||||
"title": "رزرو نوبت پزشکی",
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
**نحوه عملکرد:**
|
||||
|
||||
- در `lib/getStateInfo.js`: بررسی subdomain و تطبیق با شهر
|
||||
- در `app/layout.js`: تولید Metadata داینامیک بر اساس شهر
|
||||
- در `context/ProvinceProvider.js`: مدیریت Context شهر/استان
|
||||
|
||||
### 2. سیستم احراز هویت
|
||||
|
||||
```javascript
|
||||
// lib/auth.js - دریافت اطلاعات کاربر از Cookie
|
||||
export async function getUser() {
|
||||
const cookieStore = cookies();
|
||||
const raw =
|
||||
cookieStore.get("access_token") &&
|
||||
cookieStore.get("refresh_token") &&
|
||||
cookieStore.get("uuid") &&
|
||||
cookieStore.get("userInfo");
|
||||
return raw ? raw : null;
|
||||
}
|
||||
|
||||
// lib/ability.js - تعریف دسترسیها
|
||||
export function defineAbilitiesFor(user) {
|
||||
if (user) {
|
||||
can("access", "Dashboard");
|
||||
const parsedData = JSON.parse(user.value);
|
||||
if (parsedData.roles.find((item) => item === "representation")) {
|
||||
can("access", "Panel");
|
||||
}
|
||||
} else {
|
||||
can("access", "Login");
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3. سیستم رزرو نوبت
|
||||
|
||||
فرآیند رزرو نوبت شامل مراحل زیر است:
|
||||
|
||||
1. **انتخاب تاریخ و زمان** (`components/appointment/date/`)
|
||||
2. **ورود یا ثبتنام** (در صورت نیاز)
|
||||
3. **وارد کردن اطلاعات بیمار** (`components/appointment/detail/`)
|
||||
4. **پرداخت** (`components/appointment/paying/`)
|
||||
5. **تایید نهایی** (`components/appointment/successPay/`)
|
||||
|
||||
### 4. پنل مدیریتی
|
||||
|
||||
پنل مدیریتی برای نمایندگان شامل:
|
||||
|
||||
- **داشبورد**: نمای کلی آمار
|
||||
- **حساب کاربری**: مدیریت پروفایل
|
||||
- **افزودن پزشک**: ثبت پزشک جدید
|
||||
- **مدیریت نوبتها**: مشاهده و مدیریت نوبتها
|
||||
|
||||
**محافظت مسیر:**
|
||||
|
||||
```javascript
|
||||
// app/panel/(layout)/layout.js
|
||||
async function LayoutPanel({ children }) {
|
||||
const user = await getUser();
|
||||
const ability = defineAbilitiesFor(user);
|
||||
|
||||
if (!ability.can("access", "Panel")) {
|
||||
return redirect("/");
|
||||
}
|
||||
|
||||
return <Content>{children}</Content>;
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🚀 راهاندازی پروژه
|
||||
|
||||
### پیشنیازها
|
||||
|
||||
- **Node.js** 18+
|
||||
- **npm** یا **yarn**
|
||||
- **Docker** (اختیاری)
|
||||
|
||||
### نصب و راهاندازی
|
||||
|
||||
```bash
|
||||
# 1. کلون کردن پروژه
|
||||
git clone [repository-url]
|
||||
cd nobat724_front
|
||||
|
||||
# 2. نصب وابستگیها
|
||||
npm install
|
||||
# یا
|
||||
yarn install
|
||||
|
||||
# 3. ایجاد فایل .env.local
|
||||
cp .env.example .env.local
|
||||
|
||||
# 4. تنظیم متغیرهای محیطی
|
||||
# ویرایش .env.local:
|
||||
NEXT_PUBLIC_API_URL=http://localhost:8000
|
||||
NEXT_PUBLIC_CLIENT_ID=your_client_id
|
||||
NEXT_PUBLIC_CLIENT_SECRET=your_client_secret
|
||||
DEV_MODE=TRUE
|
||||
|
||||
# 5. اجرای پروژه در حالت Development
|
||||
npm run dev
|
||||
# یا
|
||||
yarn dev
|
||||
|
||||
# پروژه در http://localhost:3000 اجرا میشود
|
||||
```
|
||||
|
||||
### اسکریپتهای موجود
|
||||
|
||||
```json
|
||||
{
|
||||
"dev": "cross-env HOST=yazd-nobat.localhost PORT=3000 next dev",
|
||||
"build": "next build",
|
||||
"start": "next start",
|
||||
"lint": "next lint"
|
||||
}
|
||||
```
|
||||
|
||||
### راهاندازی با Docker
|
||||
|
||||
```bash
|
||||
# Build و اجرا
|
||||
docker-compose up -d
|
||||
|
||||
# مشاهده لاگها
|
||||
docker-compose logs -f
|
||||
|
||||
# توقف
|
||||
docker-compose down
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🌐 سیستم Multi-Domain
|
||||
|
||||
### ساختار دامنهها
|
||||
|
||||
پروژه از **subdomain-based routing** استفاده میکند:
|
||||
|
||||
```
|
||||
nobat724.com → سایت اصلی (همه شهرها)
|
||||
tabriz-nobat.ir → تبریز
|
||||
urmia-nobat.ir → ارومیه
|
||||
yazd-nobat.ir → یزد
|
||||
```
|
||||
|
||||
### فرآیند تشخیص شهر
|
||||
|
||||
```javascript
|
||||
// lib/getStateInfo.js (Server-Side)
|
||||
export function getStateInfo() {
|
||||
const headersList = headers();
|
||||
const host = headersList.get("host") || "";
|
||||
const subdomain = host.split(".")[0];
|
||||
|
||||
const matchedCity = citiesData.find((city) =>
|
||||
city.domain.includes(subdomain)
|
||||
);
|
||||
|
||||
return { matchedCity, matchedState };
|
||||
}
|
||||
|
||||
// context/ProvinceProvider.js (Client-Side)
|
||||
export const ProvinceProvider = ({ children }) => {
|
||||
const [hostName, setHostName] = useState("");
|
||||
const isProvinceInclude = citiesData.find((city) =>
|
||||
hostName.includes(city.domain.split(".")[0])
|
||||
);
|
||||
|
||||
return (
|
||||
<ProvinceContext.Provider value={{ isProvinceInclude }}>
|
||||
{children}
|
||||
</ProvinceContext.Provider>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
### Metadata داینامیک بر اساس شهر
|
||||
|
||||
```javascript
|
||||
// app/layout.js
|
||||
export async function generateMetadata() {
|
||||
const { matchedCity } = getStateInfo();
|
||||
|
||||
return {
|
||||
title: matchedCity ? matchedCity.title : "نوبت724",
|
||||
description: matchedCity ? matchedCity.description : "توضیحات پیشفرض",
|
||||
keywords: matchedCity ? matchedCity.keywords : "کلمات کلیدی پیشفرض",
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔐 احراز هویت و مجوزها
|
||||
|
||||
### فرآیند ورود
|
||||
|
||||
1. **ورود شماره موبایل** (`/login`)
|
||||
2. **دریافت کد OTP**
|
||||
3. **تایید کد** (`/login-verify`)
|
||||
4. **ذخیره توکنها در Cookie**
|
||||
5. **Redirect به Dashboard یا Panel**
|
||||
|
||||
### Cookies استفاده شده
|
||||
|
||||
- `access_token`: JWT Token
|
||||
- `refresh_token`: Refresh Token
|
||||
- `uuid`: شناسه کاربر
|
||||
- `userInfo`: اطلاعات کاربر
|
||||
|
||||
### محافظت از مسیرها
|
||||
|
||||
**مثال - محافظت از Panel:**
|
||||
|
||||
```javascript
|
||||
// app/panel/(layout)/layout.js
|
||||
async function LayoutPanel({ children }) {
|
||||
const user = await getUser();
|
||||
const ability = defineAbilitiesFor(user);
|
||||
|
||||
if (!ability.can("access", "Panel")) {
|
||||
return redirect("/");
|
||||
}
|
||||
|
||||
return <Content>{children}</Content>;
|
||||
}
|
||||
```
|
||||
|
||||
**مثال - محافظت از صفحه Login:**
|
||||
|
||||
```javascript
|
||||
// app/login/page.js
|
||||
async function LogIn() {
|
||||
const user = await getUser();
|
||||
const ability = defineAbilitiesFor(user);
|
||||
|
||||
if (!ability.can("access", "Login")) {
|
||||
return redirect("/");
|
||||
}
|
||||
|
||||
return <ContentLogin />;
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📍 مسیرها و صفحات
|
||||
|
||||
### صفحات عمومی (Public)
|
||||
|
||||
| مسیر | توضیحات | فایل |
|
||||
| ---------------- | -------------- | --------------------------- |
|
||||
| `/` | صفحه اصلی | `app/page.js` |
|
||||
| `/doctors` | لیست پزشکان | `app/doctors/page.js` |
|
||||
| `/doctor/[slug]` | جزئیات پزشک | `app/doctor/[slug]/page.js` |
|
||||
| `/clinics` | لیست کلینیکها | `app/clinics/page.js` |
|
||||
| `/clinic/[slug]` | جزئیات کلینیک | `app/clinic/[slug]/page.js` |
|
||||
| `/specialties` | تخصصهای پزشکی | `app/specialties/page.js` |
|
||||
| `/blogs` | لیست بلاگها | `app/blogs/page.js` |
|
||||
| `/blog/[slug]` | جزئیات بلاگ | `app/blog/[slug]/page.js` |
|
||||
| `/about-us` | درباره ما | `app/about-us/page.js` |
|
||||
| `/contact-us` | تماس با ما | `app/contact-us/page.js` |
|
||||
|
||||
### صفحات رزرو نوبت
|
||||
|
||||
| مسیر | توضیحات |
|
||||
| ------------------------- | -------------- |
|
||||
| `/appointment/[doctorId]` | صفحه رزرو نوبت |
|
||||
|
||||
### صفحات احراز هویت
|
||||
|
||||
| مسیر | توضیحات | محافظت |
|
||||
| --------------- | --------- | ----------------- |
|
||||
| `/login` | ورود | فقط کاربران مهمان |
|
||||
| `/login-verify` | تایید OTP | فقط کاربران مهمان |
|
||||
|
||||
### پنل مدیریتی (Protected)
|
||||
|
||||
| مسیر | توضیحات | دسترسی |
|
||||
| --------------------- | -------------- | --------- |
|
||||
| `/panel/dashboard` | داشبورد | نمایندگان |
|
||||
| `/panel/user-account` | حساب کاربری | نمایندگان |
|
||||
| `/panel/add-doctor` | افزودن پزشک | نمایندگان |
|
||||
| `/panel/turns` | مدیریت نوبتها | نمایندگان |
|
||||
|
||||
---
|
||||
|
||||
## 🧩 کامپوننتهای اصلی
|
||||
|
||||
### Layout Components
|
||||
|
||||
**1. Root Layout (`app/layout.js`)**
|
||||
|
||||
- Metadata داینامیک
|
||||
- Theme Provider
|
||||
- Province Provider
|
||||
- Google Analytics
|
||||
- Custom Toastify
|
||||
|
||||
**2. Public Layout (`components/layout/StLayout.js`)**
|
||||
|
||||
- Header
|
||||
- Footer
|
||||
- ScrollToTop
|
||||
|
||||
**3. Panel Layout (`components/layoutPanel/`)**
|
||||
|
||||
- Sidebar
|
||||
- Header
|
||||
- User Detail
|
||||
|
||||
### Feature Components
|
||||
|
||||
**Home Page (`components/home/`)**
|
||||
|
||||
- Search Bar
|
||||
- Text Header
|
||||
- Frequent Searches
|
||||
|
||||
**Doctor List (`components/doctors/`)**
|
||||
|
||||
- Filter Sidebar
|
||||
- Doctor Cards
|
||||
- Pagination
|
||||
|
||||
**Doctor Detail (`components/doctor/`)**
|
||||
|
||||
- Doctor Info
|
||||
- Appointment List
|
||||
- Comments
|
||||
- Share
|
||||
|
||||
**Appointment (`components/appointment/`)**
|
||||
|
||||
- Date Picker
|
||||
- Time Slots
|
||||
- Patient Details
|
||||
- Payment
|
||||
- Success/Fail Pages
|
||||
|
||||
**Panel (`components/panel/`)**
|
||||
|
||||
- Dashboard Stats
|
||||
- Doctor Management
|
||||
- Appointment Management
|
||||
- User Profile
|
||||
|
||||
---
|
||||
|
||||
## 🔌 API و سرویسها
|
||||
|
||||
### تنظیمات Axios (`services/api.js`)
|
||||
|
||||
```javascript
|
||||
const BASE_URL = process.env.NEXT_PUBLIC_API_URL;
|
||||
const token = Cookies.get("access_token");
|
||||
|
||||
const api = axios.create({
|
||||
baseURL: BASE_URL,
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
Authorization: token ? `Bearer ${token}` : "",
|
||||
},
|
||||
});
|
||||
|
||||
api.interceptors.response.use(
|
||||
(response) => response.data,
|
||||
(error) => Promise.reject(error)
|
||||
);
|
||||
```
|
||||
|
||||
### API Endpoints (`services/response.js`)
|
||||
|
||||
**دستهبندی Endpoints:**
|
||||
|
||||
```javascript
|
||||
// Authentication
|
||||
postLogin(data);
|
||||
getUserInfo(headers);
|
||||
|
||||
// Doctors
|
||||
getDoctors(params);
|
||||
getDoctor(slug);
|
||||
postDoctor(data);
|
||||
getDoctorServices();
|
||||
|
||||
// Clinics
|
||||
getClinics(params);
|
||||
getClinic(slug);
|
||||
getClinicDoctors(slug, params);
|
||||
|
||||
// Appointments
|
||||
getAppointment(doctor_id, date);
|
||||
postAppointment(data);
|
||||
getAppointmentNotAvailable(doctor_id);
|
||||
getAppointmentWeeklySchedule(uuid);
|
||||
postAppointmentWeeklySchedule();
|
||||
patchAppointmentWeeklySchedule(uuid);
|
||||
deleteAppointmentWeeklySchedule(uuid);
|
||||
|
||||
// User Profile
|
||||
getUserProfile(uuid);
|
||||
postUserProfile(data);
|
||||
patchUserProfile(data, uuid, token);
|
||||
|
||||
// Categories
|
||||
getSpecialties();
|
||||
getInsuranceType();
|
||||
|
||||
// File Upload
|
||||
postImageUpload(data);
|
||||
```
|
||||
|
||||
### Helper Functions (`helper/index.js`)
|
||||
|
||||
```javascript
|
||||
// تبدیل اعداد به فرمت عربی
|
||||
export const numberToArStyle = (num) => num?.toLocaleString("ar-AE") || "";
|
||||
|
||||
// تبدیل تاریخ میلادی به شمسی
|
||||
export const convertToJalali = (date) => {
|
||||
const jalaliDate = moment(date).format("jYYYY/jM/jD");
|
||||
// ...
|
||||
};
|
||||
|
||||
// بررسی URL فعال
|
||||
export const isActiveURL = (link, name) => link === name;
|
||||
|
||||
// آپلود تصویر
|
||||
export const uploadImage = async (event) => {
|
||||
// ...
|
||||
};
|
||||
|
||||
// ساخت Query String برای فیلتر پزشکان
|
||||
export const buildDoctorParams = (searchParams) => {
|
||||
// ...
|
||||
};
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🎨 استایلدهی
|
||||
|
||||
### Tailwind CSS
|
||||
|
||||
پروژه از **Tailwind CSS** برای استایلدهی استفاده میکند:
|
||||
|
||||
```javascript
|
||||
// tailwind.config.js
|
||||
module.exports = {
|
||||
content: [
|
||||
"./pages/**/*.{js,ts,jsx,tsx,mdx}",
|
||||
"./components/**/*.{js,ts,jsx,tsx,mdx}",
|
||||
"./app/**/*.{js,ts,jsx,tsx,mdx}",
|
||||
],
|
||||
darkMode: "class",
|
||||
theme: {
|
||||
extend: {
|
||||
// Custom colors, fonts, etc.
|
||||
},
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
### Material-UI Theme
|
||||
|
||||
```javascript
|
||||
// mui/index.js
|
||||
const theme = createTheme({
|
||||
direction: "rtl",
|
||||
typography: {
|
||||
fontFamily: "IRANSans, Arial",
|
||||
},
|
||||
palette: {
|
||||
primary: { main: "#5559CE" },
|
||||
// ...
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
### Dark Mode
|
||||
|
||||
```javascript
|
||||
// app/Providers.js
|
||||
export function Providers({ children }) {
|
||||
const router = usePathname();
|
||||
|
||||
return (
|
||||
<ThemeProvider
|
||||
attribute={router.includes("/panel") ? "class" : "data-"}
|
||||
defaultTheme="system"
|
||||
enableSystem
|
||||
>
|
||||
{children}
|
||||
</ThemeProvider>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🐳 Deployment
|
||||
|
||||
### متغیرهای محیطی مورد نیاز
|
||||
|
||||
```env
|
||||
# API Configuration
|
||||
NEXT_PUBLIC_API_URL=https://api.nobat724.com
|
||||
NEXT_PUBLIC_CLIENT_ID=your_client_id
|
||||
NEXT_PUBLIC_CLIENT_SECRET=your_client_secret
|
||||
|
||||
# Development Mode (TRUE/FALSE)
|
||||
DEV_MODE=FALSE
|
||||
|
||||
# Application Port
|
||||
APP_PORT=3000
|
||||
|
||||
# Node Environment
|
||||
NODE_ENV=production
|
||||
```
|
||||
|
||||
### Build Production
|
||||
|
||||
```bash
|
||||
# Build
|
||||
npm run build
|
||||
|
||||
# Start Production Server
|
||||
npm run start
|
||||
```
|
||||
|
||||
### Docker Deployment
|
||||
|
||||
```bash
|
||||
# Build Image
|
||||
docker build -t nobat724-front .
|
||||
|
||||
# Run Container
|
||||
docker run -p 3000:3000 \
|
||||
-e NEXT_PUBLIC_API_URL=https://api.nobat724.com \
|
||||
-e DEV_MODE=FALSE \
|
||||
nobat724-front
|
||||
```
|
||||
|
||||
### Docker Compose
|
||||
|
||||
```yaml
|
||||
# docker-compose.yml
|
||||
version: "3.8"
|
||||
|
||||
services:
|
||||
frontend:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "${APP_PORT}:3000"
|
||||
environment:
|
||||
- NEXT_PUBLIC_API_URL=${NEXT_PUBLIC_API_URL}
|
||||
- DEV_MODE=${DEV_MODE}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📝 نکات توسعه
|
||||
|
||||
### 1. افزودن صفحه جدید
|
||||
|
||||
```javascript
|
||||
// app/new-page/page.js
|
||||
import Layout from "@/components/layout/StLayout";
|
||||
|
||||
export default function NewPage() {
|
||||
return (
|
||||
<Layout>
|
||||
<div>محتوای صفحه جدید</div>
|
||||
</Layout>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
### 2. افزودن API Endpoint جدید
|
||||
|
||||
```javascript
|
||||
// services/response.js
|
||||
export const request = {
|
||||
// ...
|
||||
getNewData: () => api.get("api/v1/new-endpoint"),
|
||||
postNewData: (data) => api.post("api/v1/new-endpoint", data),
|
||||
};
|
||||
```
|
||||
|
||||
### 3. افزودن کامپوننت جدید
|
||||
|
||||
```javascript
|
||||
// components/NewComponent/index.js
|
||||
"use client"; // اگر Client Component است
|
||||
|
||||
function NewComponent({ data }) {
|
||||
return <div>{/* محتوای کامپوننت */}</div>;
|
||||
}
|
||||
|
||||
export default NewComponent;
|
||||
```
|
||||
|
||||
### 4. کار با تاریخ شمسی
|
||||
|
||||
```javascript
|
||||
import moment from "jalali-moment";
|
||||
|
||||
// تبدیل میلادی به شمسی
|
||||
const jalaliDate = moment("2024-01-15").format("jYYYY/jMM/jDD");
|
||||
|
||||
// تبدیل شمسی به میلادی
|
||||
const gregorianDate = moment("1402/10/25", "jYYYY/jMM/jDD").format(
|
||||
"YYYY-MM-DD"
|
||||
);
|
||||
```
|
||||
|
||||
### 5. استفاده از Context
|
||||
|
||||
```javascript
|
||||
"use client";
|
||||
import { useProvince } from "@/context/ProvinceProvider";
|
||||
|
||||
function MyComponent() {
|
||||
const { isProvinceInclude } = useProvince();
|
||||
|
||||
return <div>{isProvinceInclude && <p>شهر: {isProvinceInclude.name}</p>}</div>;
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔧 Troubleshooting
|
||||
|
||||
### مشکلات رایج
|
||||
|
||||
**1. خطای Hydration**
|
||||
|
||||
```
|
||||
Error: Text content does not match server-rendered HTML
|
||||
```
|
||||
|
||||
**راهحل:** استفاده از `useEffect` برای محتوای Client-Side
|
||||
|
||||
**2. خطای Authentication**
|
||||
|
||||
```
|
||||
Unauthorized (401)
|
||||
```
|
||||
|
||||
**راهحل:** بررسی توکن در Cookie و تنظیم Header
|
||||
|
||||
**3. مشکل Dark Mode**
|
||||
|
||||
```
|
||||
Flash of unstyled content
|
||||
```
|
||||
|
||||
**راهحل:** استفاده صحیح از `next-themes` و `ThemeProvider`
|
||||
|
||||
---
|
||||
|
||||
## 📚 منابع مفید
|
||||
|
||||
- [Next.js Documentation](https://nextjs.org/docs)
|
||||
- [Material-UI Documentation](https://mui.com/)
|
||||
- [Tailwind CSS Documentation](https://tailwindcss.com/docs)
|
||||
- [CASL Documentation](https://casl.js.org/v6/en/)
|
||||
- [Jalali Moment](https://github.com/jalaali/moment-jalaali)
|
||||
|
||||
---
|
||||
|
||||
## 👥 تیم توسعه
|
||||
|
||||
**Senior Frontend Developer**: شما! 🎉
|
||||
|
||||
**Tech Stack Expertise:**
|
||||
|
||||
- ✅ Next.js 14 (App Router)
|
||||
- ✅ React.js 18
|
||||
- ✅ Material-UI v7
|
||||
- ✅ Tailwind CSS
|
||||
- ✅ Server Components & Client Components
|
||||
- ✅ Authentication & Authorization
|
||||
- ✅ Multi-Domain Architecture
|
||||
- ✅ Persian/Jalali Date Handling
|
||||
|
||||
---
|
||||
|
||||
## 📞 پشتیبانی
|
||||
|
||||
برای هرگونه سوال یا مشکل:
|
||||
|
||||
- 📧 Email: nobat724@gmail.com
|
||||
- 🌐 Website: https://nobat724.com
|
||||
|
||||
---
|
||||
|
||||
**تاریخ آخرین بهروزرسانی:** نوامبر 2025
|
||||
|
||||
**نسخه پروژه:** 0.1.0
|
||||
|
||||
Reference in New Issue
Block a user