feat: update UI to glassmorphic design and copper theme

This commit is contained in:
Behrad
2026-09-08 02:06:32 +03:30
parent 35a558db20
commit ddd986e037
94 changed files with 6973 additions and 959 deletions
+42 -7
View File
@@ -1,14 +1,15 @@
# بک‌اند گروه ساختمانی آرامش (Aramesh Building Group API)
بک‌اند سایت گروه ساختمانی آرامش — ساخته‌شده با **FastAPI** + **PostgreSQL** + **SQLAlchemy 2** + **JWT**.
بک‌اند سایت گروه ساختمانی آرامش — ساخته‌شده با **FastAPI** + **PostgreSQL** + **SQLAlchemy 2** + **JWT** + **MinIO** (ذخیره تصاویر) + **Traefik** (مسیریابی).
## امکانات
- **API عمومی محتوا**: برند، خدمات، پروژه‌ها، مقالات، نظرات مشتریان، سوالات متداول، تیم، تایم‌لاین، آمار، چرا آرامش، و بخش قبل/بعد
- **API عمومی محتوا**: برند، منو، هیرو، داستان، تیتر بخش‌ها، هیرو صفحات، خدمات، پروژه‌ها، مقالات، نظرات مشتریان، سوالات متداول، تیم، تایم‌لاین، آمار، چرا آرامش، قبل/بعد، مدل‌های سرمایه‌گذاری، مراحل کار، دفاتر، گالری، فرم تماس، خبرنامه و فوتر — **تمام متن‌های سایت در دیتابیس است**
- **فرم تماس**: ثبت پیام مشتریان از سایت (`POST /api/contact`)
- **خبرنامه**: عضویت و مدیریت مشترکین (`POST /api/newsletter`)
- **پنل مدیریت**: ورود با نام کاربری/رمز عبور و دریافت توکن JWT، سپس CRUD کامل همه محتواها، مدیریت پیام‌های تماس و مشترکین
- **Seed خودکار**: همه محتوای فعلی سایت با یک دستور در دیتابیس قرار می‌گیرد
- **آپلود تصویر**: `POST /api/admin/upload` — فایل در MinIO ذخیره و URL نسبی `/media/...` برمی‌گردد
- **Seed خودکار**: همه محتوای فعلی سایت با یک دستور در دیتابیس قرار می‌گیرد (فقط جدول‌های خالی پر می‌شوند — ارتقا بدون از دست رفتن داده)
- مستندات تعاملی Swagger در مسیر `/docs`
## راه‌اندازی
@@ -85,6 +86,13 @@ Authorization: Bearer <access_token>
> نام کاربری و رمز عبور پیش‌فرض از تنظیمات `.env` خوانده می‌شود — حتماً در محیط تولید تغییرشان دهید.
تغییر رمز (با توکن):
```
POST /api/auth/change-password
{ "current_password": "...", "new_password": "..." }
```
## فهرست انتهاپوینت‌ها
### عمومی (بدون نیاز به توکن)
@@ -96,8 +104,8 @@ Authorization: Bearer <access_token>
| GET | `/api/services` | خدمات |
| GET | `/api/projects` | همه پروژه‌ها |
| GET | `/api/projects/{slug}` | جزئیات یک پروژه |
| GET | `/api/articles` | همه مقالات |
| GET | `/api/articles/{slug}` | جزئیات یک مقاله |
| GET | `/api/articles` | مقاله‌های منتشرشده (پیش‌نویس نمی‌آید) |
| GET | `/api/articles/{slug}` | جزئیات یک مقاله منتشرشده |
| GET | `/api/testimonials` | نظرات مشتریان |
| GET | `/api/faqs` | سوالات متداول |
| GET | `/api/team` | اعضای تیم |
@@ -108,7 +116,11 @@ Authorization: Bearer <access_token>
| GET | `/api/site` | **همه محتوا در یک درخواست** |
| POST | `/api/contact` | ثبت پیام تماس |
| POST | `/api/newsletter` | عضویت در خبرنامه |
| POST | `/api/auth/login` | ورود ادمین و دریافت توکن |
| POST | `/api/auth/login` | ورود ادمین و دریافت توکن — بعد از ۵ تلاش ناموفق در ۱۵ دقیقه، 429 |
| GET | `/robots.txt` | قوانین خزنده‌ها |
| GET | `/sitemap.xml` | نقشه سایت — مقاله/پروژه‌های منتشرشده |
| GET | `/blog/{slug}` | HTML صفحه مقاله با متای سئوی تزریق‌شده |
| GET | `/projects/{slug}` | HTML صفحه پروژه با متای سئوی تزریق‌شده |
### مدیریت (نیاز به توکن Bearer)
@@ -118,12 +130,35 @@ Authorization: Bearer <access_token>
| متد | مسیر | توضیح |
|---|---|---|
| GET/POST | `/api/admin/{resource}` | لیست / ساخت |
| GET/PUT/DELETE | `/api/admin/{resource}/{id}` | دریافت / ویرایش / حذف |
| GET/PUT/DELETE | `/api/admin/{resource}/{id}` | دریافت / ویرایش کامل / حذف |
| PATCH | `/api/admin/{resource}/{id}` | **ویرایش جزئی** — فقط فیلدهای ارسال‌شده به‌روزرسانی می‌شوند |
| POST | `/api/admin/{resource}/reorder` | ذخیره ترتیب: `{"ids": [3, 1, 2, ...]}` |
| GET | `/api/admin/messages` | پیام‌های تماس (با `?unread_only=true` فقط خوانده‌نشده‌ها) |
| PATCH | `/api/admin/messages/{id}` | تغییر وضعیت خوانده‌شدن |
| DELETE | `/api/admin/messages/{id}` | حذف پیام |
| GET | `/api/admin/subscribers` | مشترکین خبرنامه |
| DELETE | `/api/admin/subscribers/{id}` | حذف مشترک |
| POST | `/api/admin/upload` | آپلود تصویر (multipart، حداکثر ۱۰MB — jpg/png/webp/gif/avif) → `{"url": "/media/..."}` |
### بدنه مقاله — سند TipTap
`body` مقاله یک سند ساختاریافته TipTap (ProseMirror JSON) است: `{"type": "doc", "content": [...]}`.
- فقط ساختار اعتبارسنجی می‌شود (`type: "doc"` + `content` لیست)؛ امنیت رندر بر عهده
رندر استاتیک TipTap در فرانت‌اند است که فقط تگ‌های شناخته‌شده تولید می‌کند
- ردیف‌های قدیمی (لیست پاراگراف) با مهاجرت idempotent `migrate_article_bodies`
در startup/seed خودکار به سند تبدیل می‌شوند
- seed هم بدنه‌های لیستی را قبل از درج تبدیل می‌کند
| POST/PATCH | `/api/admin/seo-meta` | عنوان و توضیح متای صفحات — `page_key`: home / about / services / projects / investment / blog / faq / contact |
منابعی که `reorder` دارند (ستون `position`): `services`، `projects`، `articles`، `testimonials`، `faqs`، `team`، `timeline`، `stats`، `why-us`، `investment-models`، `process-steps`، `offices`، `gallery`، `nav`. ستون با مهاجرت سبک idempotent هنگام startup/seed به دیتابیس‌های موجود اضافه می‌شود.
### تصاویر و MinIO
فایل‌های آپلودشده در باکت `aramesh-media` روی MinIO ذخیره می‌شوند و با مسیر نسبی `/media/<سال>/<ماه>/<فایل>` برگردانده می‌شوند. Traefik مسیر `/media` را به MinIO می‌برد، پس URLها مستقل از بک‌اند ذخیره‌سازی هستند — بعداً برای مهاجرت به R2/S3 فقط تنظیمات را عوض کنید، نه محتوای دیتابیس را.
- کنسول MinIO: `http://localhost:9001` (کاربر/رمز از `MINIO_ROOT_USER` / `MINIO_ROOT_PASSWORD` در compose)
- تصاویر عمومی و قابل نمایش‌اند؛ آپلود فقط با توکن ادمین انجام می‌شود.
## اتصال به فرانت‌اند