Add comprehensive project documentation for ClinicPro in CLAUDE.md and README.md
- Introduced CLAUDE.md for internal guidance on project structure, commands, and architecture. - Created README.md with detailed project overview, technology stack, directory structure, setup instructions, API endpoints, authentication flow, and external services.
This commit is contained in:
@@ -17,11 +17,13 @@ use App\Sms\Entity\SmsLog;
|
||||
use App\Sms\Entity\SmsTemplate;
|
||||
use App\Shared\Controller\BaseController;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use OpenApi\Attributes as OA;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||
|
||||
#[OA\Tag(name: 'Admin')]
|
||||
#[IsGranted('ROLE_ADMIN')]
|
||||
class AdminApiController extends BaseController
|
||||
{
|
||||
@@ -31,6 +33,46 @@ class AdminApiController extends BaseController
|
||||
|
||||
// ── Users ─────────────────────────────────────────────────────────────────
|
||||
|
||||
#[OA\Get(
|
||||
path: '/api/v1/admin/users',
|
||||
summary: 'List all users (paginated)',
|
||||
security: [['bearerAuth' => []]],
|
||||
parameters: [
|
||||
new OA\Parameter(name: 'page', in: 'query', required: false, schema: new OA\Schema(type: 'integer', default: 1)),
|
||||
new OA\Parameter(name: 'limit', in: 'query', required: false, schema: new OA\Schema(type: 'integer', default: 15)),
|
||||
new OA\Parameter(name: 'search', in: 'query', required: false, schema: new OA\Schema(type: 'string')),
|
||||
],
|
||||
responses: [
|
||||
new OA\Response(
|
||||
response: 200,
|
||||
description: 'Paginated list of users',
|
||||
content: new OA\JsonContent(
|
||||
properties: [
|
||||
new OA\Property(property: 'success', type: 'boolean', example: true),
|
||||
new OA\Property(property: 'data', type: 'array', items: new OA\Items(
|
||||
properties: [
|
||||
new OA\Property(property: 'uuid', type: 'string'),
|
||||
new OA\Property(property: 'id', type: 'integer'),
|
||||
new OA\Property(property: 'mobile_number', type: 'string'),
|
||||
new OA\Property(property: 'name', type: 'string'),
|
||||
new OA\Property(property: 'email', type: 'string'),
|
||||
new OA\Property(property: 'roles', type: 'array', items: new OA\Items(type: 'string')),
|
||||
new OA\Property(property: 'is_active', type: 'boolean'),
|
||||
new OA\Property(property: 'created_at', type: 'string', format: 'date-time'),
|
||||
]
|
||||
)),
|
||||
new OA\Property(property: 'meta', properties: [
|
||||
new OA\Property(property: 'totalRecords', type: 'integer'),
|
||||
new OA\Property(property: 'totalPages', type: 'integer'),
|
||||
new OA\Property(property: 'currentPage', type: 'integer'),
|
||||
], type: 'object'),
|
||||
]
|
||||
)
|
||||
),
|
||||
new OA\Response(response: 401, description: 'Unauthorized'),
|
||||
new OA\Response(response: 403, description: 'Forbidden – ROLE_ADMIN required'),
|
||||
]
|
||||
)]
|
||||
#[Route('/api/v1/admin/users', methods: ['GET'])]
|
||||
public function users(Request $request): JsonResponse
|
||||
{
|
||||
@@ -69,6 +111,48 @@ class AdminApiController extends BaseController
|
||||
|
||||
// ── Appointments ──────────────────────────────────────────────────────────
|
||||
|
||||
#[OA\Get(
|
||||
path: '/api/v1/admin/appointments',
|
||||
summary: 'List all appointments (paginated)',
|
||||
security: [['bearerAuth' => []]],
|
||||
parameters: [
|
||||
new OA\Parameter(name: 'page', in: 'query', required: false, schema: new OA\Schema(type: 'integer', default: 1)),
|
||||
new OA\Parameter(name: 'limit', in: 'query', required: false, schema: new OA\Schema(type: 'integer', default: 15)),
|
||||
new OA\Parameter(name: 'search', in: 'query', required: false, schema: new OA\Schema(type: 'string')),
|
||||
new OA\Parameter(name: 'status', in: 'query', required: false, schema: new OA\Schema(type: 'string')),
|
||||
],
|
||||
responses: [
|
||||
new OA\Response(
|
||||
response: 200,
|
||||
description: 'Paginated list of appointments',
|
||||
content: new OA\JsonContent(
|
||||
properties: [
|
||||
new OA\Property(property: 'success', type: 'boolean', example: true),
|
||||
new OA\Property(property: 'data', type: 'array', items: new OA\Items(
|
||||
properties: [
|
||||
new OA\Property(property: 'uuid', type: 'string'),
|
||||
new OA\Property(property: 'patient_name', type: 'string'),
|
||||
new OA\Property(property: 'patient_mobile', type: 'string'),
|
||||
new OA\Property(property: 'doctor_name', type: 'string'),
|
||||
new OA\Property(property: 'appointment_date', type: 'string', format: 'date'),
|
||||
new OA\Property(property: 'appointment_time', type: 'string', example: '14:30'),
|
||||
new OA\Property(property: 'status', type: 'string'),
|
||||
new OA\Property(property: 'amount', type: 'integer'),
|
||||
new OA\Property(property: 'created_at', type: 'string', format: 'date-time'),
|
||||
]
|
||||
)),
|
||||
new OA\Property(property: 'meta', properties: [
|
||||
new OA\Property(property: 'totalRecords', type: 'integer'),
|
||||
new OA\Property(property: 'totalPages', type: 'integer'),
|
||||
new OA\Property(property: 'currentPage', type: 'integer'),
|
||||
], type: 'object'),
|
||||
]
|
||||
)
|
||||
),
|
||||
new OA\Response(response: 401, description: 'Unauthorized'),
|
||||
new OA\Response(response: 403, description: 'Forbidden – ROLE_ADMIN required'),
|
||||
]
|
||||
)]
|
||||
#[Route('/api/v1/admin/appointments', methods: ['GET'])]
|
||||
public function appointments(Request $request): JsonResponse
|
||||
{
|
||||
@@ -118,6 +202,46 @@ class AdminApiController extends BaseController
|
||||
|
||||
// ── Payments ──────────────────────────────────────────────────────────────
|
||||
|
||||
#[OA\Get(
|
||||
path: '/api/v1/admin/payments',
|
||||
summary: 'List all payments (paginated)',
|
||||
security: [['bearerAuth' => []]],
|
||||
parameters: [
|
||||
new OA\Parameter(name: 'page', in: 'query', required: false, schema: new OA\Schema(type: 'integer', default: 1)),
|
||||
new OA\Parameter(name: 'limit', in: 'query', required: false, schema: new OA\Schema(type: 'integer', default: 15)),
|
||||
new OA\Parameter(name: 'status', in: 'query', required: false, schema: new OA\Schema(type: 'string', enum: ['pending', 'success', 'failed'])),
|
||||
],
|
||||
responses: [
|
||||
new OA\Response(
|
||||
response: 200,
|
||||
description: 'Paginated list of payments',
|
||||
content: new OA\JsonContent(
|
||||
properties: [
|
||||
new OA\Property(property: 'success', type: 'boolean', example: true),
|
||||
new OA\Property(property: 'data', type: 'array', items: new OA\Items(
|
||||
properties: [
|
||||
new OA\Property(property: 'uuid', type: 'string'),
|
||||
new OA\Property(property: 'amount', type: 'integer'),
|
||||
new OA\Property(property: 'status', type: 'string'),
|
||||
new OA\Property(property: 'gateway', type: 'string'),
|
||||
new OA\Property(property: 'ref_id', type: 'string', nullable: true),
|
||||
new OA\Property(property: 'patient_mobile', type: 'string'),
|
||||
new OA\Property(property: 'paid_at', type: 'string', format: 'date-time', nullable: true),
|
||||
new OA\Property(property: 'created_at', type: 'string', format: 'date-time'),
|
||||
]
|
||||
)),
|
||||
new OA\Property(property: 'meta', properties: [
|
||||
new OA\Property(property: 'totalRecords', type: 'integer'),
|
||||
new OA\Property(property: 'totalPages', type: 'integer'),
|
||||
new OA\Property(property: 'currentPage', type: 'integer'),
|
||||
], type: 'object'),
|
||||
]
|
||||
)
|
||||
),
|
||||
new OA\Response(response: 401, description: 'Unauthorized'),
|
||||
new OA\Response(response: 403, description: 'Forbidden – ROLE_ADMIN required'),
|
||||
]
|
||||
)]
|
||||
#[Route('/api/v1/admin/payments', methods: ['GET'])]
|
||||
public function payments(Request $request): JsonResponse
|
||||
{
|
||||
@@ -164,6 +288,49 @@ class AdminApiController extends BaseController
|
||||
|
||||
// ── Representations ───────────────────────────────────────────────────────
|
||||
|
||||
#[OA\Get(
|
||||
path: '/api/v1/admin/representations',
|
||||
summary: 'List all representations (paginated)',
|
||||
security: [['bearerAuth' => []]],
|
||||
parameters: [
|
||||
new OA\Parameter(name: 'page', in: 'query', required: false, schema: new OA\Schema(type: 'integer', default: 1)),
|
||||
new OA\Parameter(name: 'limit', in: 'query', required: false, schema: new OA\Schema(type: 'integer', default: 15)),
|
||||
new OA\Parameter(name: 'search', in: 'query', required: false, schema: new OA\Schema(type: 'string')),
|
||||
new OA\Parameter(name: 'city_id', in: 'query', required: false, schema: new OA\Schema(type: 'integer')),
|
||||
],
|
||||
responses: [
|
||||
new OA\Response(
|
||||
response: 200,
|
||||
description: 'Paginated list of representations',
|
||||
content: new OA\JsonContent(
|
||||
properties: [
|
||||
new OA\Property(property: 'success', type: 'boolean', example: true),
|
||||
new OA\Property(property: 'data', type: 'array', items: new OA\Items(
|
||||
properties: [
|
||||
new OA\Property(property: 'uuid', type: 'string'),
|
||||
new OA\Property(property: 'domain', type: 'string'),
|
||||
new OA\Property(property: 'full_name', type: 'string'),
|
||||
new OA\Property(property: 'mobile_number', type: 'string'),
|
||||
new OA\Property(property: 'city_id', type: 'integer', nullable: true),
|
||||
new OA\Property(property: 'city', type: 'string', nullable: true),
|
||||
new OA\Property(property: 'commission_percent', type: 'number', format: 'float'),
|
||||
new OA\Property(property: 'wallet_balance', type: 'integer'),
|
||||
new OA\Property(property: 'is_active', type: 'boolean'),
|
||||
new OA\Property(property: 'created_at', type: 'string', format: 'date-time'),
|
||||
]
|
||||
)),
|
||||
new OA\Property(property: 'meta', properties: [
|
||||
new OA\Property(property: 'totalRecords', type: 'integer'),
|
||||
new OA\Property(property: 'totalPages', type: 'integer'),
|
||||
new OA\Property(property: 'currentPage', type: 'integer'),
|
||||
], type: 'object'),
|
||||
]
|
||||
)
|
||||
),
|
||||
new OA\Response(response: 401, description: 'Unauthorized'),
|
||||
new OA\Response(response: 403, description: 'Forbidden – ROLE_ADMIN required'),
|
||||
]
|
||||
)]
|
||||
#[Route('/api/v1/admin/representations', methods: ['GET'])]
|
||||
public function representations(Request $request): JsonResponse
|
||||
{
|
||||
@@ -211,6 +378,46 @@ class AdminApiController extends BaseController
|
||||
|
||||
// ── Secretaries ───────────────────────────────────────────────────────────
|
||||
|
||||
#[OA\Get(
|
||||
path: '/api/v1/admin/secretaries',
|
||||
summary: 'List all secretaries (paginated)',
|
||||
security: [['bearerAuth' => []]],
|
||||
parameters: [
|
||||
new OA\Parameter(name: 'page', in: 'query', required: false, schema: new OA\Schema(type: 'integer', default: 1)),
|
||||
new OA\Parameter(name: 'limit', in: 'query', required: false, schema: new OA\Schema(type: 'integer', default: 15)),
|
||||
new OA\Parameter(name: 'search', in: 'query', required: false, schema: new OA\Schema(type: 'string')),
|
||||
],
|
||||
responses: [
|
||||
new OA\Response(
|
||||
response: 200,
|
||||
description: 'Paginated list of secretaries',
|
||||
content: new OA\JsonContent(
|
||||
properties: [
|
||||
new OA\Property(property: 'success', type: 'boolean', example: true),
|
||||
new OA\Property(property: 'data', type: 'array', items: new OA\Items(
|
||||
properties: [
|
||||
new OA\Property(property: 'uuid', type: 'string'),
|
||||
new OA\Property(property: 'user_name', type: 'string'),
|
||||
new OA\Property(property: 'mobile_number', type: 'string'),
|
||||
new OA\Property(property: 'doctor_name', type: 'string'),
|
||||
new OA\Property(property: 'doctor_uuid', type: 'string'),
|
||||
new OA\Property(property: 'is_active', type: 'boolean'),
|
||||
new OA\Property(property: 'permissions', type: 'array', items: new OA\Items(type: 'string')),
|
||||
new OA\Property(property: 'created_at', type: 'string', format: 'date-time'),
|
||||
]
|
||||
)),
|
||||
new OA\Property(property: 'meta', properties: [
|
||||
new OA\Property(property: 'totalRecords', type: 'integer'),
|
||||
new OA\Property(property: 'totalPages', type: 'integer'),
|
||||
new OA\Property(property: 'currentPage', type: 'integer'),
|
||||
], type: 'object'),
|
||||
]
|
||||
)
|
||||
),
|
||||
new OA\Response(response: 401, description: 'Unauthorized'),
|
||||
new OA\Response(response: 403, description: 'Forbidden – ROLE_ADMIN required'),
|
||||
]
|
||||
)]
|
||||
#[Route('/api/v1/admin/secretaries', methods: ['GET'])]
|
||||
public function secretaries(Request $request): JsonResponse
|
||||
{
|
||||
@@ -255,6 +462,44 @@ class AdminApiController extends BaseController
|
||||
|
||||
// ── Ratings ───────────────────────────────────────────────────────────────
|
||||
|
||||
#[OA\Get(
|
||||
path: '/api/v1/admin/rates',
|
||||
summary: 'List all ratings (paginated)',
|
||||
security: [['bearerAuth' => []]],
|
||||
parameters: [
|
||||
new OA\Parameter(name: 'page', in: 'query', required: false, schema: new OA\Schema(type: 'integer', default: 1)),
|
||||
new OA\Parameter(name: 'limit', in: 'query', required: false, schema: new OA\Schema(type: 'integer', default: 15)),
|
||||
new OA\Parameter(name: 'search', in: 'query', required: false, schema: new OA\Schema(type: 'string')),
|
||||
],
|
||||
responses: [
|
||||
new OA\Response(
|
||||
response: 200,
|
||||
description: 'Paginated list of ratings',
|
||||
content: new OA\JsonContent(
|
||||
properties: [
|
||||
new OA\Property(property: 'success', type: 'boolean', example: true),
|
||||
new OA\Property(property: 'data', type: 'array', items: new OA\Items(
|
||||
properties: [
|
||||
new OA\Property(property: 'uuid', type: 'string'),
|
||||
new OA\Property(property: 'patient_name', type: 'string'),
|
||||
new OA\Property(property: 'doctor_name', type: 'string'),
|
||||
new OA\Property(property: 'overall', type: 'integer'),
|
||||
new OA\Property(property: 'score', type: 'integer'),
|
||||
new OA\Property(property: 'created_at', type: 'string', format: 'date-time'),
|
||||
]
|
||||
)),
|
||||
new OA\Property(property: 'meta', properties: [
|
||||
new OA\Property(property: 'totalRecords', type: 'integer'),
|
||||
new OA\Property(property: 'totalPages', type: 'integer'),
|
||||
new OA\Property(property: 'currentPage', type: 'integer'),
|
||||
], type: 'object'),
|
||||
]
|
||||
)
|
||||
),
|
||||
new OA\Response(response: 401, description: 'Unauthorized'),
|
||||
new OA\Response(response: 403, description: 'Forbidden – ROLE_ADMIN required'),
|
||||
]
|
||||
)]
|
||||
#[Route('/api/v1/admin/rates', methods: ['GET'])]
|
||||
public function rates(Request $request): JsonResponse
|
||||
{
|
||||
@@ -297,6 +542,47 @@ class AdminApiController extends BaseController
|
||||
|
||||
// ── Comments ──────────────────────────────────────────────────────────────
|
||||
|
||||
#[OA\Get(
|
||||
path: '/api/v1/admin/comments',
|
||||
summary: 'List all comments (paginated)',
|
||||
security: [['bearerAuth' => []]],
|
||||
parameters: [
|
||||
new OA\Parameter(name: 'page', in: 'query', required: false, schema: new OA\Schema(type: 'integer', default: 1)),
|
||||
new OA\Parameter(name: 'limit', in: 'query', required: false, schema: new OA\Schema(type: 'integer', default: 15)),
|
||||
new OA\Parameter(name: 'search', in: 'query', required: false, schema: new OA\Schema(type: 'string')),
|
||||
new OA\Parameter(name: 'status', in: 'query', required: false, schema: new OA\Schema(type: 'string', enum: ['pending', 'approved', 'rejected'])),
|
||||
],
|
||||
responses: [
|
||||
new OA\Response(
|
||||
response: 200,
|
||||
description: 'Paginated list of comments',
|
||||
content: new OA\JsonContent(
|
||||
properties: [
|
||||
new OA\Property(property: 'success', type: 'boolean', example: true),
|
||||
new OA\Property(property: 'data', type: 'array', items: new OA\Items(
|
||||
properties: [
|
||||
new OA\Property(property: 'uuid', type: 'string'),
|
||||
new OA\Property(property: 'patient_name', type: 'string'),
|
||||
new OA\Property(property: 'doctor_name', type: 'string'),
|
||||
new OA\Property(property: 'title', type: 'string'),
|
||||
new OA\Property(property: 'body', type: 'string'),
|
||||
new OA\Property(property: 'is_approved', type: 'boolean'),
|
||||
new OA\Property(property: 'status', type: 'string'),
|
||||
new OA\Property(property: 'created_at', type: 'string', format: 'date-time'),
|
||||
]
|
||||
)),
|
||||
new OA\Property(property: 'meta', properties: [
|
||||
new OA\Property(property: 'totalRecords', type: 'integer'),
|
||||
new OA\Property(property: 'totalPages', type: 'integer'),
|
||||
new OA\Property(property: 'currentPage', type: 'integer'),
|
||||
], type: 'object'),
|
||||
]
|
||||
)
|
||||
),
|
||||
new OA\Response(response: 401, description: 'Unauthorized'),
|
||||
new OA\Response(response: 403, description: 'Forbidden – ROLE_ADMIN required'),
|
||||
]
|
||||
)]
|
||||
#[Route('/api/v1/admin/comments', methods: ['GET'])]
|
||||
public function comments(Request $request): JsonResponse
|
||||
{
|
||||
@@ -345,6 +631,44 @@ class AdminApiController extends BaseController
|
||||
|
||||
// ── SMS Logs ──────────────────────────────────────────────────────────────
|
||||
|
||||
#[OA\Get(
|
||||
path: '/api/v1/admin/sms/logs',
|
||||
summary: 'List SMS send logs (paginated)',
|
||||
security: [['bearerAuth' => []]],
|
||||
parameters: [
|
||||
new OA\Parameter(name: 'page', in: 'query', required: false, schema: new OA\Schema(type: 'integer', default: 1)),
|
||||
new OA\Parameter(name: 'limit', in: 'query', required: false, schema: new OA\Schema(type: 'integer', default: 15)),
|
||||
],
|
||||
responses: [
|
||||
new OA\Response(
|
||||
response: 200,
|
||||
description: 'Paginated list of SMS logs',
|
||||
content: new OA\JsonContent(
|
||||
properties: [
|
||||
new OA\Property(property: 'success', type: 'boolean', example: true),
|
||||
new OA\Property(property: 'data', type: 'array', items: new OA\Items(
|
||||
properties: [
|
||||
new OA\Property(property: 'uuid', type: 'string'),
|
||||
new OA\Property(property: 'recipient', type: 'string'),
|
||||
new OA\Property(property: 'message', type: 'string'),
|
||||
new OA\Property(property: 'status', type: 'string', enum: ['sent', 'failed']),
|
||||
new OA\Property(property: 'provider', type: 'string'),
|
||||
new OA\Property(property: 'sent_at', type: 'string', format: 'date-time'),
|
||||
new OA\Property(property: 'created_at', type: 'string', format: 'date-time'),
|
||||
]
|
||||
)),
|
||||
new OA\Property(property: 'meta', properties: [
|
||||
new OA\Property(property: 'totalRecords', type: 'integer'),
|
||||
new OA\Property(property: 'totalPages', type: 'integer'),
|
||||
new OA\Property(property: 'currentPage', type: 'integer'),
|
||||
], type: 'object'),
|
||||
]
|
||||
)
|
||||
),
|
||||
new OA\Response(response: 401, description: 'Unauthorized'),
|
||||
new OA\Response(response: 403, description: 'Forbidden – ROLE_ADMIN required'),
|
||||
]
|
||||
)]
|
||||
#[Route('/api/v1/admin/sms/logs', methods: ['GET'])]
|
||||
public function smsLogs(Request $request): JsonResponse
|
||||
{
|
||||
@@ -376,6 +700,47 @@ class AdminApiController extends BaseController
|
||||
|
||||
// ── Settlements ───────────────────────────────────────────────────────────
|
||||
|
||||
#[OA\Get(
|
||||
path: '/api/v1/admin/settlements',
|
||||
summary: 'List all settlement requests (paginated)',
|
||||
security: [['bearerAuth' => []]],
|
||||
parameters: [
|
||||
new OA\Parameter(name: 'page', in: 'query', required: false, schema: new OA\Schema(type: 'integer', default: 1)),
|
||||
new OA\Parameter(name: 'limit', in: 'query', required: false, schema: new OA\Schema(type: 'integer', default: 15)),
|
||||
new OA\Parameter(name: 'status', in: 'query', required: false, schema: new OA\Schema(type: 'string', enum: ['pending', 'approved', 'rejected'])),
|
||||
],
|
||||
responses: [
|
||||
new OA\Response(
|
||||
response: 200,
|
||||
description: 'Paginated list of settlement requests',
|
||||
content: new OA\JsonContent(
|
||||
properties: [
|
||||
new OA\Property(property: 'success', type: 'boolean', example: true),
|
||||
new OA\Property(property: 'data', type: 'array', items: new OA\Items(
|
||||
properties: [
|
||||
new OA\Property(property: 'uuid', type: 'string'),
|
||||
new OA\Property(property: 'representation_name', type: 'string'),
|
||||
new OA\Property(property: 'amount', type: 'integer'),
|
||||
new OA\Property(property: 'status', type: 'string'),
|
||||
new OA\Property(property: 'bank_card', type: 'string', nullable: true),
|
||||
new OA\Property(property: 'bank_name', type: 'string', nullable: true),
|
||||
new OA\Property(property: 'reject_reason', type: 'string', nullable: true),
|
||||
new OA\Property(property: 'requested_at', type: 'string', format: 'date-time'),
|
||||
new OA\Property(property: 'processed_at', type: 'string', format: 'date-time', nullable: true),
|
||||
]
|
||||
)),
|
||||
new OA\Property(property: 'meta', properties: [
|
||||
new OA\Property(property: 'totalRecords', type: 'integer'),
|
||||
new OA\Property(property: 'totalPages', type: 'integer'),
|
||||
new OA\Property(property: 'currentPage', type: 'integer'),
|
||||
], type: 'object'),
|
||||
]
|
||||
)
|
||||
),
|
||||
new OA\Response(response: 401, description: 'Unauthorized'),
|
||||
new OA\Response(response: 403, description: 'Forbidden – ROLE_ADMIN required'),
|
||||
]
|
||||
)]
|
||||
#[Route('/api/v1/admin/settlements', methods: ['GET'])]
|
||||
public function settlements(Request $request): JsonResponse
|
||||
{
|
||||
@@ -418,6 +783,45 @@ class AdminApiController extends BaseController
|
||||
|
||||
// ── SMS Templates (paginated list with optional status filter) ────────────
|
||||
|
||||
#[OA\Get(
|
||||
path: '/api/v1/admin/sms/sample-templates',
|
||||
summary: 'List SMS sample templates (paginated)',
|
||||
security: [['bearerAuth' => []]],
|
||||
parameters: [
|
||||
new OA\Parameter(name: 'page', in: 'query', required: false, schema: new OA\Schema(type: 'integer', default: 1)),
|
||||
new OA\Parameter(name: 'limit', in: 'query', required: false, schema: new OA\Schema(type: 'integer', default: 15)),
|
||||
new OA\Parameter(name: 'status', in: 'query', required: false, schema: new OA\Schema(type: 'string', enum: ['approved', 'pending'], default: 'approved')),
|
||||
],
|
||||
responses: [
|
||||
new OA\Response(
|
||||
response: 200,
|
||||
description: 'Paginated list of SMS templates',
|
||||
content: new OA\JsonContent(
|
||||
properties: [
|
||||
new OA\Property(property: 'success', type: 'boolean', example: true),
|
||||
new OA\Property(property: 'data', type: 'array', items: new OA\Items(
|
||||
properties: [
|
||||
new OA\Property(property: 'uuid', type: 'string'),
|
||||
new OA\Property(property: 'name', type: 'string'),
|
||||
new OA\Property(property: 'body', type: 'string'),
|
||||
new OA\Property(property: 'provider_code', type: 'string', nullable: true),
|
||||
new OA\Property(property: 'status', type: 'string'),
|
||||
new OA\Property(property: 'admin_note', type: 'string', nullable: true),
|
||||
new OA\Property(property: 'created_at', type: 'string', format: 'date-time'),
|
||||
]
|
||||
)),
|
||||
new OA\Property(property: 'meta', properties: [
|
||||
new OA\Property(property: 'totalRecords', type: 'integer'),
|
||||
new OA\Property(property: 'totalPages', type: 'integer'),
|
||||
new OA\Property(property: 'currentPage', type: 'integer'),
|
||||
], type: 'object'),
|
||||
]
|
||||
)
|
||||
),
|
||||
new OA\Response(response: 401, description: 'Unauthorized'),
|
||||
new OA\Response(response: 403, description: 'Forbidden – ROLE_ADMIN required'),
|
||||
]
|
||||
)]
|
||||
#[Route('/api/v1/admin/sms/sample-templates', methods: ['GET'])]
|
||||
public function smsSampleTemplates(Request $request): JsonResponse
|
||||
{
|
||||
@@ -454,6 +858,57 @@ class AdminApiController extends BaseController
|
||||
|
||||
// ── Dashboard Recent ──────────────────────────────────────────────────────
|
||||
|
||||
#[OA\Get(
|
||||
path: '/api/v1/admin/dashboard/recent',
|
||||
summary: 'Get recent dashboard data (appointments, payments, users)',
|
||||
security: [['bearerAuth' => []]],
|
||||
responses: [
|
||||
new OA\Response(
|
||||
response: 200,
|
||||
description: 'Recent dashboard data',
|
||||
content: new OA\JsonContent(
|
||||
properties: [
|
||||
new OA\Property(property: 'success', type: 'boolean', example: true),
|
||||
new OA\Property(property: 'data', properties: [
|
||||
new OA\Property(property: 'appointments', type: 'array', items: new OA\Items(
|
||||
properties: [
|
||||
new OA\Property(property: 'uuid', type: 'string'),
|
||||
new OA\Property(property: 'slot_start', type: 'string', format: 'date-time'),
|
||||
new OA\Property(property: 'status', type: 'string'),
|
||||
new OA\Property(property: 'doctor_name', type: 'string'),
|
||||
new OA\Property(property: 'user_mobile', type: 'string'),
|
||||
new OA\Property(property: 'user_name', type: 'string'),
|
||||
new OA\Property(property: 'created_at', type: 'string', format: 'date-time'),
|
||||
]
|
||||
)),
|
||||
new OA\Property(property: 'payments', type: 'array', items: new OA\Items(
|
||||
properties: [
|
||||
new OA\Property(property: 'uuid', type: 'string'),
|
||||
new OA\Property(property: 'amount', type: 'integer'),
|
||||
new OA\Property(property: 'status', type: 'string'),
|
||||
new OA\Property(property: 'gateway', type: 'string'),
|
||||
new OA\Property(property: 'user_mobile', type: 'string'),
|
||||
new OA\Property(property: 'user_name', type: 'string'),
|
||||
new OA\Property(property: 'created_at', type: 'string', format: 'date-time'),
|
||||
]
|
||||
)),
|
||||
new OA\Property(property: 'users', type: 'array', items: new OA\Items(
|
||||
properties: [
|
||||
new OA\Property(property: 'uuid', type: 'string'),
|
||||
new OA\Property(property: 'mobile', type: 'string'),
|
||||
new OA\Property(property: 'name', type: 'string'),
|
||||
new OA\Property(property: 'email', type: 'string', nullable: true),
|
||||
new OA\Property(property: 'created_at', type: 'string', format: 'date-time'),
|
||||
]
|
||||
)),
|
||||
], type: 'object'),
|
||||
]
|
||||
)
|
||||
),
|
||||
new OA\Response(response: 401, description: 'Unauthorized'),
|
||||
new OA\Response(response: 403, description: 'Forbidden – ROLE_ADMIN required'),
|
||||
]
|
||||
)]
|
||||
#[Route('/api/v1/admin/dashboard/recent', methods: ['GET'])]
|
||||
public function dashboardRecent(): JsonResponse
|
||||
{
|
||||
@@ -521,6 +976,37 @@ class AdminApiController extends BaseController
|
||||
|
||||
// ── Dashboard Stats ───────────────────────────────────────────────────────
|
||||
|
||||
#[OA\Get(
|
||||
path: '/api/v1/admin/dashboard/stats',
|
||||
summary: 'Get aggregated dashboard statistics',
|
||||
security: [['bearerAuth' => []]],
|
||||
responses: [
|
||||
new OA\Response(
|
||||
response: 200,
|
||||
description: 'Dashboard statistics',
|
||||
content: new OA\JsonContent(
|
||||
properties: [
|
||||
new OA\Property(property: 'success', type: 'boolean', example: true),
|
||||
new OA\Property(property: 'data', properties: [
|
||||
new OA\Property(property: 'total_users', type: 'integer'),
|
||||
new OA\Property(property: 'active_doctors', type: 'integer'),
|
||||
new OA\Property(property: 'total_doctors', type: 'integer'),
|
||||
new OA\Property(property: 'total_clinics', type: 'integer'),
|
||||
new OA\Property(property: 'today_appointments', type: 'integer'),
|
||||
new OA\Property(property: 'total_appointments', type: 'integer'),
|
||||
new OA\Property(property: 'today_payments_count', type: 'integer'),
|
||||
new OA\Property(property: 'today_payments_amount', type: 'integer'),
|
||||
new OA\Property(property: 'total_payments_amount', type: 'integer'),
|
||||
new OA\Property(property: 'pending_comments', type: 'integer'),
|
||||
new OA\Property(property: 'pending_settlements', type: 'integer'),
|
||||
], type: 'object'),
|
||||
]
|
||||
)
|
||||
),
|
||||
new OA\Response(response: 401, description: 'Unauthorized'),
|
||||
new OA\Response(response: 403, description: 'Forbidden – ROLE_ADMIN required'),
|
||||
]
|
||||
)]
|
||||
#[Route('/api/v1/admin/dashboard/stats', methods: ['GET'])]
|
||||
public function dashboardStats(): JsonResponse
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user