- Removed the "دکتر" prefix from doctor names in various components and API responses to ensure consistency and clarity. - Updated the AppointmentDetailPage, CommentsPage, DashboardPage, RatingsPage, SecretariesPage, and other relevant files to reflect the changes in doctor name formatting. - Adjusted API documentation to align with the new naming conventions. - Implemented validation to prevent the creation of clinics without a name and restricted users to a single clinic. - Added tests to verify that doctor names are stored without titles and that clinic creation adheres to the new validation rules.
7.4 KiB
Blog API
Prefix:
/api/v1/blog,/api/v1/blogs
GET /api/v1/blogs
List published blog posts.
Permission: PUBLIC
Query Parameters
| Param | Type | Required | Default | Description |
|---|---|---|---|---|
page |
integer | ❌ | 1 | Page number |
limit |
integer | ❌ | 20 | Items per page |
tag |
string | ❌ | — | Filter by exact tag name (e.g. ?tag=دیابت). Blog tags are stored as a JSON array of names; only blogs whose tags array contains this exact name are returned. |
city_id |
integer | ❌ | — | Scope to one city. Returns that city's posts plus every nationwide post (city_id IS NULL). Omit it to return all published posts regardless of city. |
Response 200
{
"success": true,
"data": [
{
"uuid": "...",
"title": "آشنایی با بیماری دیابت",
"slug": "ashnayi-ba-bimari-diabat",
"summary": "خلاصه مطلب...",
"image": "https://...",
"author": { "uuid": "...", "real_name": "احمدی" },
"tags": [{ "id": 1, "name": "دیابت" }],
"status": "published",
"city": { "id": "123", "name": "یاسوج" },
"created_at": 1717000000
}
],
"meta": {
"totalRecords": 25,
"totalPages": 2,
"currentPage": 1,
"limit": 20
}
}
فیلد city — شهر پست
city در پاسخ لیست و جزئیات وجود دارد و دو حالت دارد:
| مقدار | معنا |
|---|---|
{ "id": "123", "name": "یاسوج" } |
پست شهری — به آن شهر تعلق دارد |
null |
پست سراسری — حالت دائمی و معتبر، نه «تنظیمنشده» |
city_idرویblogsnullable است وNULLمعنای دائمی «سراسری» دارد. رکوردهای قبل از این تغییر همگی سراسری شدند.- حذف شهر پست را حذف نمیکند (
ON DELETE SET NULL) — پست سراسری میشود. - پست سراسری روی همهٔ دامنههای شهری در لیست دیده میشود؛ فقط canonical آن روی دامنهٔ اصلی مینشیند. به همین دلیل
city_id=Xهم پستهای شهر X و هم پستهای سراسری را برمیگرداند — نه فقط شهر X.
🔗 مصرفکننده: سایت عمومی چند-دامنهای (
nobat724_front) با همین فیلد تصمیم میگیرد پست را روی دامنهٔ شهر canonical کند یا روی دامنهٔ اصلی، و در کدام sitemap بگذارد. تغییر معنایnullقرارداد آن را میشکند.
GET /api/v1/blog/{slug}
Get a single blog post by slug.
Permission: PUBLIC
Path Parameters
| Param | Type | Description |
|---|---|---|
slug |
string | URL slug (e.g. ashnayi-ba-bimari-diabat) |
Response 200
{
"success": true,
"data": {
"uuid": "...",
"title": "آشنایی با بیماری دیابت",
"slug": "ashnayi-ba-bimari-diabat",
"summary": "خلاصه...",
"body": "<p>محتوای کامل...</p>",
"image": "https://...",
"author": { "uuid": "...", "real_name": "احمدی" },
"tags": [{ "id": 1, "name": "دیابت" }],
"status": "published",
"created_at": 1717000000,
"updated_at": 1717100000
}
}
Errors
| Code | HTTP | Description |
|---|---|---|
ERR_NOT_FOUND_001 |
404 | Blog not found or not published |
POST /api/v1/blog
Create a new blog post.
Permission: ROLE_ADMIN
Request Body (application/json)
{
"title": "آشنایی با بیماری دیابت",
"body": "<p>محتوای کامل مقاله...</p>",
"summary": "خلاصه کوتاه از مقاله",
"tags": [1, 2],
"status": "draft",
"image_url": "/uploads/blogs/blog_abc.jpg"
}
| Field | Type | Required | Description |
|---|---|---|---|
title |
string | ✅ | Post title (slug auto-generated) |
body |
string | ✅ | Full HTML body (from the admin CKEditor) |
summary |
string | ❌ | Short excerpt |
tags |
integer[] | ❌ | Array of tag IDs |
status |
string | ❌ | "draft" (default) or "published" |
image_url |
string | ❌ | Cover image path returned by the upload endpoint |
city_id |
integer|null | ❌ | City this post belongs to. Omitting it, or sending null/0, creates a nationwide post. An unknown city id is rejected with 422. |
Response 201
{
"success": true,
"data": {
"uuid": "blog-uuid-...",
"title": "آشنایی با بیماری دیابت",
"slug": "ashnayi-ba-bimari-diabat",
"summary": "...",
"body": "...",
"image": null,
"tags": [],
"status": "draft",
"created_at": 1717000000
}
}
Blog Status Values:
| Value | Description |
|---|---|
draft |
Not visible to public |
published |
Visible in public listing |
archived |
Hidden from listing |
Errors
| Code | HTTP | Description |
|---|---|---|
ERR_AUTH_001 |
401 | Missing token |
ERR_AUTH_006 |
403 | Not admin |
ERR_VALIDATION_002 |
422 | Missing required fields |
PATCH /api/v1/blog/{uuid}
Update a blog post.
Permission: ROLE_ADMIN
Path Parameters
| Param | Type | Description |
|---|---|---|
uuid |
string (UUID) | Blog UUID |
Request Body (application/json)
{
"title": "عنوان جدید",
"body": "<p>محتوای جدید</p>",
"summary": "خلاصه جدید",
"tags": [1, 3],
"status": "published",
"image_url": "/uploads/blogs/blog_abc.jpg"
}
All fields optional. Send image_url: "" to clear the cover image.
city_id follows PATCH semantics: omit it and the post's city is left untouched; send null (or 0) to turn the post into a nationwide one; send a city id to move it to that city.
Response 200
Updated blog object.
Errors
| Code | HTTP | Description |
|---|---|---|
ERR_AUTH_001 |
401 | Missing token |
ERR_AUTH_006 |
403 | Not admin |
ERR_NOT_FOUND_001 |
404 | Blog not found |
ERR_VALIDATION_002 |
422 | Unknown city_id |
DELETE /api/v1/blog/{uuid}
Delete a blog post.
Permission: ROLE_ADMIN
Response 200
{ "success": true, "data": { "message": "مقاله حذف شد" } }
Errors
| Code | HTTP | Description |
|---|---|---|
ERR_AUTH_001 |
401 | Missing token |
ERR_AUTH_006 |
403 | Not admin |
ERR_NOT_FOUND_001 |
404 | Blog not found |
POST /file/upload/clinic_pro/blog/field_image
Upload blog post header image.
Permission: ROLE_ADMIN
Request
Content-Type: multipart/form-data
| Field | Type | Required | Description |
|---|---|---|---|
file |
binary | ✅ | Image (max 5MB) |
blog_uuid |
string (UUID) | ❌ | Auto-associate with blog post |
Response 200
{
"success": true,
"data": {
"url": "https://clinic-pro.ddev.site/uploads/blog/post_abc.jpg",
"uuid": "...",
"filename": "post_abc.jpg",
"filemime": "image/jpeg",
"filesize": 204800
}
}
Errors
| Code | HTTP | Description |
|---|---|---|
ERR_AUTH_001 |
401 | Missing token |
ERR_AUTH_006 |
403 | Not admin |
ERR_FILE_001 |
422 | Invalid file type |