add all controllers logic
This commit is contained in:
@@ -0,0 +1,30 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Console\Commands;
|
||||||
|
|
||||||
|
use Illuminate\Console\Command;
|
||||||
|
|
||||||
|
class ImportUsers extends Command
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The name and signature of the console command.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $signature = 'app:import-users';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The console command description.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $description = 'Command description';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute the console command.
|
||||||
|
*/
|
||||||
|
public function handle()
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Api\Attendance;
|
||||||
|
|
||||||
|
use App\Http\Controllers\Api\BaseApiController;
|
||||||
|
use App\Http\Requests\Attendance\LateSlipLogIndexRequest;
|
||||||
|
use App\Http\Resources\Attendance\LateSlipLogCollection;
|
||||||
|
use App\Http\Resources\Attendance\LateSlipLogResource;
|
||||||
|
use App\Models\LateSlipLog;
|
||||||
|
use App\Services\Attendance\LateSlipLogCommandService;
|
||||||
|
use App\Services\Attendance\LateSlipLogQueryService;
|
||||||
|
use Illuminate\Http\JsonResponse;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
|
|
||||||
|
class LateSlipLogsController extends BaseApiController
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
private LateSlipLogQueryService $queryService,
|
||||||
|
private LateSlipLogCommandService $commandService
|
||||||
|
) {
|
||||||
|
parent::__construct();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function index(LateSlipLogIndexRequest $request): JsonResponse
|
||||||
|
{
|
||||||
|
$this->authorize('viewAny', LateSlipLog::class);
|
||||||
|
|
||||||
|
$filters = $request->validated();
|
||||||
|
$page = (int) ($filters['page'] ?? 1);
|
||||||
|
$perPage = (int) ($filters['per_page'] ?? 50);
|
||||||
|
|
||||||
|
$logs = $this->queryService->paginate($filters, $page, $perPage);
|
||||||
|
$collection = new LateSlipLogCollection($logs);
|
||||||
|
|
||||||
|
return $this->success([
|
||||||
|
'logs' => $collection->toArray($request),
|
||||||
|
'meta' => $collection->with($request)['meta'],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function show(int $id): JsonResponse
|
||||||
|
{
|
||||||
|
$log = $this->queryService->find($id);
|
||||||
|
if (!$log) {
|
||||||
|
return $this->error('Late slip log not found.', Response::HTTP_NOT_FOUND);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->authorize('view', $log);
|
||||||
|
|
||||||
|
return $this->success([
|
||||||
|
'log' => new LateSlipLogResource($log),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function destroy(int $id): JsonResponse
|
||||||
|
{
|
||||||
|
$log = $this->queryService->find($id);
|
||||||
|
if (!$log) {
|
||||||
|
return $this->error('Late slip log not found.', Response::HTTP_NOT_FOUND);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->authorize('delete', $log);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$deleted = $this->commandService->delete($log);
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
Log::error('Late slip log delete failed: ' . $e->getMessage());
|
||||||
|
return $this->error('Unable to delete late slip log.', Response::HTTP_INTERNAL_SERVER_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$deleted) {
|
||||||
|
return $this->error('Unable to delete late slip log.', Response::HTTP_INTERNAL_SERVER_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->success(null, 'Late slip log deleted.');
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,115 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Api\Auth;
|
||||||
|
|
||||||
|
use App\Http\Controllers\Api\BaseApiController;
|
||||||
|
use App\Http\Requests\Security\IpBanIndexRequest;
|
||||||
|
use App\Http\Requests\Security\IpBanRequest;
|
||||||
|
use App\Http\Requests\Security\IpUnbanRequest;
|
||||||
|
use App\Http\Resources\Security\IpBanCollection;
|
||||||
|
use App\Http\Resources\Security\IpBanResource;
|
||||||
|
use App\Models\IpAttempt;
|
||||||
|
use App\Services\Security\IpBanCommandService;
|
||||||
|
use App\Services\Security\IpBanQueryService;
|
||||||
|
use Illuminate\Http\JsonResponse;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
|
|
||||||
|
class IpBanController extends BaseApiController
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
private IpBanQueryService $queryService,
|
||||||
|
private IpBanCommandService $commandService
|
||||||
|
) {
|
||||||
|
parent::__construct();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function index(IpBanIndexRequest $request): JsonResponse
|
||||||
|
{
|
||||||
|
$this->authorize('viewAny', IpAttempt::class);
|
||||||
|
|
||||||
|
$filters = $request->validated();
|
||||||
|
$page = (int) ($filters['page'] ?? 1);
|
||||||
|
$perPage = (int) ($filters['per_page'] ?? 20);
|
||||||
|
|
||||||
|
$bans = $this->queryService->paginate($filters, $page, $perPage);
|
||||||
|
$collection = new IpBanCollection($bans);
|
||||||
|
|
||||||
|
return $this->success([
|
||||||
|
'bans' => $collection->toArray($request),
|
||||||
|
'meta' => $collection->with($request)['meta'],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function show(int $id): JsonResponse
|
||||||
|
{
|
||||||
|
$ban = $this->queryService->find($id);
|
||||||
|
if (!$ban) {
|
||||||
|
return $this->error('IP record not found.', Response::HTTP_NOT_FOUND);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->authorize('view', $ban);
|
||||||
|
|
||||||
|
return $this->success([
|
||||||
|
'ban' => new IpBanResource($ban),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function ban(IpBanRequest $request): JsonResponse
|
||||||
|
{
|
||||||
|
$this->authorize('create', IpAttempt::class);
|
||||||
|
|
||||||
|
$validated = $request->validated();
|
||||||
|
$id = $validated['id'] ?? null;
|
||||||
|
$ip = $validated['ip'] ?? null;
|
||||||
|
$hours = (int) ($validated['hours'] ?? 24);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$ban = $this->commandService->banNow($id ? (int) $id : null, $ip ? (string) $ip : null, $hours);
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
Log::error('IP ban failed: ' . $e->getMessage());
|
||||||
|
return $this->error('Unable to ban IP.', Response::HTTP_INTERNAL_SERVER_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$ban) {
|
||||||
|
return $this->error('IP record not found.', Response::HTTP_NOT_FOUND);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->success([
|
||||||
|
'ban' => new IpBanResource($ban),
|
||||||
|
], 'IP banned.');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function unban(IpUnbanRequest $request): JsonResponse
|
||||||
|
{
|
||||||
|
$this->authorize('update', IpAttempt::class);
|
||||||
|
|
||||||
|
$validated = $request->validated();
|
||||||
|
$all = filter_var($validated['all'] ?? false, FILTER_VALIDATE_BOOLEAN);
|
||||||
|
|
||||||
|
try {
|
||||||
|
if ($all) {
|
||||||
|
$count = $this->commandService->unbanAll();
|
||||||
|
return $this->success([
|
||||||
|
'count' => $count,
|
||||||
|
], $count . ' IP(s) unbanned.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$ban = $this->commandService->unbanOne(
|
||||||
|
isset($validated['id']) ? (int) $validated['id'] : null,
|
||||||
|
$validated['ip'] ?? null
|
||||||
|
);
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
Log::error('IP unban failed: ' . $e->getMessage());
|
||||||
|
return $this->error('Unable to unban IP.', Response::HTTP_INTERNAL_SERVER_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$ban) {
|
||||||
|
return $this->error('IP record not found.', Response::HTTP_NOT_FOUND);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->success([
|
||||||
|
'ban' => new IpBanResource($ban),
|
||||||
|
], 'IP unbanned.');
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,67 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Http\Controllers\Api\Auth;
|
|
||||||
|
|
||||||
use App\Http\Controllers\Api\BaseApiController;
|
|
||||||
use App\Http\Requests\Auth\SessionTimeoutCheckRequest;
|
|
||||||
use App\Http\Requests\Auth\SessionTimeoutConfigRequest;
|
|
||||||
use App\Http\Requests\Auth\SessionTimeoutPingRequest;
|
|
||||||
use App\Http\Resources\Auth\SessionTimeoutConfigResource;
|
|
||||||
use App\Http\Resources\Auth\SessionTimeoutStatusResource;
|
|
||||||
use App\Services\Auth\SessionTimeoutConfigService;
|
|
||||||
use App\Services\Auth\SessionTimeoutService;
|
|
||||||
use Illuminate\Http\JsonResponse;
|
|
||||||
use Symfony\Component\HttpFoundation\Response;
|
|
||||||
|
|
||||||
class SessionTimeoutController extends BaseApiController
|
|
||||||
{
|
|
||||||
public function __construct(
|
|
||||||
private SessionTimeoutConfigService $configService,
|
|
||||||
private SessionTimeoutService $timeoutService
|
|
||||||
) {
|
|
||||||
parent::__construct();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function config(SessionTimeoutConfigRequest $request): JsonResponse
|
|
||||||
{
|
|
||||||
$config = $this->configService->config();
|
|
||||||
|
|
||||||
return $this->success([
|
|
||||||
'config' => new SessionTimeoutConfigResource($config),
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function check(SessionTimeoutCheckRequest $request): JsonResponse
|
|
||||||
{
|
|
||||||
$result = $this->timeoutService->checkTimeout();
|
|
||||||
|
|
||||||
if (($result['status'] ?? '') === 'expired') {
|
|
||||||
return $this->error(
|
|
||||||
$result['message'] ?? 'Session expired.',
|
|
||||||
Response::HTTP_UNAUTHORIZED,
|
|
||||||
(new SessionTimeoutStatusResource($result))->toArray($request)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->success([
|
|
||||||
'session' => new SessionTimeoutStatusResource($result),
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function ping(SessionTimeoutPingRequest $request): JsonResponse
|
|
||||||
{
|
|
||||||
$result = $this->timeoutService->pingActivity();
|
|
||||||
|
|
||||||
if (($result['status'] ?? '') === 'expired') {
|
|
||||||
return $this->error(
|
|
||||||
$result['message'] ?? 'Session expired.',
|
|
||||||
Response::HTTP_UNAUTHORIZED,
|
|
||||||
(new SessionTimeoutStatusResource($result))->toArray($request)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->success([
|
|
||||||
'session' => new SessionTimeoutStatusResource($result),
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -229,7 +229,7 @@ class BaseApiController extends Controller
|
|||||||
|
|
||||||
protected function getCurrentUserId(): ?int
|
protected function getCurrentUserId(): ?int
|
||||||
{
|
{
|
||||||
$userId = (int) (session()->get('user_id') ?? 0);
|
$userId = (int) (auth()->id() ?? 0);
|
||||||
return $userId > 0 ? $userId : null;
|
return $userId > 0 ? $userId : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -251,8 +251,6 @@ class BaseApiController extends Controller
|
|||||||
$name = $row['email'] ?? 'User #' . $userId;
|
$name = $row['email'] ?? 'User #' . $userId;
|
||||||
}
|
}
|
||||||
|
|
||||||
$roles = (array) (session()->get('roles') ?? []);
|
|
||||||
if (empty($roles)) {
|
|
||||||
try {
|
try {
|
||||||
$roles = DB::table('user_roles ur')
|
$roles = DB::table('user_roles ur')
|
||||||
->select('LOWER(r.name) AS name')
|
->select('LOWER(r.name) AS name')
|
||||||
@@ -268,7 +266,6 @@ class BaseApiController extends Controller
|
|||||||
Log::error('Unable to load user roles: ' . $e->getMessage());
|
Log::error('Unable to load user roles: ' . $e->getMessage());
|
||||||
$roles = [];
|
$roles = [];
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return (object) [
|
return (object) [
|
||||||
'id' => (int) $userId,
|
'id' => (int) $userId,
|
||||||
|
|||||||
@@ -3,9 +3,16 @@
|
|||||||
namespace App\Http\Controllers\Api\ClassPreparation;
|
namespace App\Http\Controllers\Api\ClassPreparation;
|
||||||
|
|
||||||
use App\Http\Controllers\Api\BaseApiController;
|
use App\Http\Controllers\Api\BaseApiController;
|
||||||
|
use App\Http\Requests\ClassPreparation\ClassPreparationAdjustmentRequest;
|
||||||
|
use App\Http\Requests\ClassPreparation\ClassPreparationIndexRequest;
|
||||||
|
use App\Http\Requests\ClassPreparation\ClassPreparationMarkPrintedRequest;
|
||||||
|
use App\Http\Requests\ClassPreparation\ClassPreparationPrintRequest;
|
||||||
|
use App\Http\Resources\ClassPreparation\ClassPreparationPrintResource;
|
||||||
|
use App\Http\Resources\ClassPreparation\ClassPreparationResultResource;
|
||||||
use App\Services\ClassPreparation\ClassPreparationService;
|
use App\Services\ClassPreparation\ClassPreparationService;
|
||||||
use Illuminate\Http\JsonResponse;
|
use Illuminate\Http\JsonResponse;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Support\Facades\Log;
|
||||||
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
|
|
||||||
class ClassPreparationController extends BaseApiController
|
class ClassPreparationController extends BaseApiController
|
||||||
{
|
{
|
||||||
@@ -17,7 +24,7 @@ class ClassPreparationController extends BaseApiController
|
|||||||
$this->service = $service;
|
$this->service = $service;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function index(Request $request): JsonResponse
|
public function index(ClassPreparationIndexRequest $request): JsonResponse
|
||||||
{
|
{
|
||||||
$schoolYear = (string) ($request->query('school_year') ?? '');
|
$schoolYear = (string) ($request->query('school_year') ?? '');
|
||||||
$semester = (string) ($request->query('semester') ?? '');
|
$semester = (string) ($request->query('semester') ?? '');
|
||||||
@@ -27,34 +34,63 @@ class ClassPreparationController extends BaseApiController
|
|||||||
$semester !== '' ? $semester : null
|
$semester !== '' ? $semester : null
|
||||||
);
|
);
|
||||||
|
|
||||||
return response()->json([
|
return $this->success([
|
||||||
'ok' => true,
|
|
||||||
'schoolYear' => $payload['schoolYear'],
|
'schoolYear' => $payload['schoolYear'],
|
||||||
'semester' => $payload['semester'],
|
'semester' => $payload['semester'],
|
||||||
'results' => $payload['results'],
|
'results' => ClassPreparationResultResource::collection($payload['results']),
|
||||||
'totals' => $payload['totals'],
|
'totals' => $payload['totals'],
|
||||||
'shortages' => $payload['shortages'],
|
'shortages' => $payload['shortages'],
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function markPrinted(Request $request): JsonResponse
|
public function markPrinted(ClassPreparationMarkPrintedRequest $request): JsonResponse
|
||||||
{
|
{
|
||||||
$schoolYear = (string) ($request->input('school_year') ?? '');
|
$validated = $request->validated();
|
||||||
$semester = (string) ($request->input('semester') ?? '');
|
$schoolYear = (string) ($validated['school_year'] ?? '');
|
||||||
$ids = $request->input('class_section_ids', []);
|
$semester = (string) ($validated['semester'] ?? '');
|
||||||
|
$ids = $validated['class_section_ids'] ?? [];
|
||||||
if ($schoolYear === '' || !is_array($ids)) {
|
|
||||||
return response()->json([
|
|
||||||
'ok' => false,
|
|
||||||
'message' => 'school_year and class_section_ids are required.',
|
|
||||||
], 422);
|
|
||||||
}
|
|
||||||
|
|
||||||
$count = $this->service->markPrinted($schoolYear, $semester, $ids);
|
$count = $this->service->markPrinted($schoolYear, $semester, $ids);
|
||||||
|
|
||||||
return response()->json([
|
return $this->success([
|
||||||
'ok' => true,
|
|
||||||
'updated' => $count,
|
'updated' => $count,
|
||||||
]);
|
], 'Class preparation logs updated.');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function saveAdjustments(ClassPreparationAdjustmentRequest $request): JsonResponse
|
||||||
|
{
|
||||||
|
$validated = $request->validated();
|
||||||
|
$classSectionId = (string) $validated['class_section_id'];
|
||||||
|
$schoolYear = (string) ($validated['school_year'] ?? '');
|
||||||
|
|
||||||
|
try {
|
||||||
|
$count = $this->service->saveAdjustments($classSectionId, $schoolYear, $validated['adjustments']);
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
Log::error('Class prep adjustment save failed: ' . $e->getMessage());
|
||||||
|
return $this->error('Unable to save adjustments.', Response::HTTP_INTERNAL_SERVER_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->success([
|
||||||
|
'updated' => $count,
|
||||||
|
], 'Adjustments saved.');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function print(ClassPreparationPrintRequest $request): JsonResponse
|
||||||
|
{
|
||||||
|
$validated = $request->validated();
|
||||||
|
|
||||||
|
$payload = $this->service->printPrep(
|
||||||
|
(string) $validated['class_section_id'],
|
||||||
|
(string) $validated['school_year'],
|
||||||
|
(string) ($validated['semester'] ?? '')
|
||||||
|
);
|
||||||
|
|
||||||
|
if (empty($payload['ok'])) {
|
||||||
|
return $this->error('Unable to log class preparation print.', Response::HTTP_INTERNAL_SERVER_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->success([
|
||||||
|
'print' => new ClassPreparationPrintResource($payload),
|
||||||
|
], 'Class preparation logged.');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,136 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Api\Classes;
|
||||||
|
|
||||||
|
use App\Http\Controllers\Api\BaseApiController;
|
||||||
|
use App\Http\Requests\Classes\ClassSectionIndexRequest;
|
||||||
|
use App\Http\Requests\Classes\ClassSectionStoreRequest;
|
||||||
|
use App\Http\Requests\Classes\ClassSectionUpdateRequest;
|
||||||
|
use App\Http\Resources\Classes\ClassAttendanceResource;
|
||||||
|
use App\Http\Resources\Classes\ClassSectionCollection;
|
||||||
|
use App\Http\Resources\Classes\ClassSectionResource;
|
||||||
|
use App\Models\ClassSection;
|
||||||
|
use App\Services\ClassSections\ClassAttendanceService;
|
||||||
|
use App\Services\ClassSections\ClassSectionCommandService;
|
||||||
|
use App\Services\ClassSections\ClassSectionQueryService;
|
||||||
|
use App\Services\ClassSections\ClassSectionSeedService;
|
||||||
|
use Illuminate\Http\JsonResponse;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
|
|
||||||
|
class ClassController extends BaseApiController
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
private ClassSectionQueryService $queryService,
|
||||||
|
private ClassSectionCommandService $commandService,
|
||||||
|
private ClassAttendanceService $attendanceService,
|
||||||
|
private ClassSectionSeedService $seedService
|
||||||
|
) {
|
||||||
|
parent::__construct();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function index(ClassSectionIndexRequest $request): JsonResponse
|
||||||
|
{
|
||||||
|
$this->authorize('viewAny', ClassSection::class);
|
||||||
|
|
||||||
|
$filters = $request->validated();
|
||||||
|
$page = (int) ($filters['page'] ?? 1);
|
||||||
|
$perPage = (int) ($filters['per_page'] ?? 20);
|
||||||
|
|
||||||
|
$sections = $this->queryService->list($filters, $page, $perPage);
|
||||||
|
$collection = new ClassSectionCollection($sections);
|
||||||
|
|
||||||
|
return $this->success([
|
||||||
|
'sections' => $collection->toArray($request),
|
||||||
|
'meta' => $collection->with($request)['meta'],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function show(ClassSection $classSection): JsonResponse
|
||||||
|
{
|
||||||
|
$this->authorize('view', $classSection);
|
||||||
|
|
||||||
|
$section = $this->queryService->find((int) $classSection->id);
|
||||||
|
|
||||||
|
if (!$section) {
|
||||||
|
return $this->error('Class section not found.', Response::HTTP_NOT_FOUND);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->success([
|
||||||
|
'section' => new ClassSectionResource($section),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function store(ClassSectionStoreRequest $request): JsonResponse
|
||||||
|
{
|
||||||
|
$this->authorize('create', ClassSection::class);
|
||||||
|
|
||||||
|
$section = $this->commandService->create($request->validated());
|
||||||
|
|
||||||
|
return $this->success([
|
||||||
|
'section' => new ClassSectionResource($section),
|
||||||
|
], 'Class section created.', Response::HTTP_CREATED);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function update(ClassSectionUpdateRequest $request, ClassSection $classSection): JsonResponse
|
||||||
|
{
|
||||||
|
$this->authorize('update', $classSection);
|
||||||
|
|
||||||
|
$section = $this->commandService->update($classSection, $request->validated());
|
||||||
|
|
||||||
|
return $this->success([
|
||||||
|
'section' => new ClassSectionResource($section),
|
||||||
|
], 'Class section updated.');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function destroy(ClassSection $classSection): JsonResponse
|
||||||
|
{
|
||||||
|
$this->authorize('delete', $classSection);
|
||||||
|
|
||||||
|
if (!$this->commandService->delete($classSection)) {
|
||||||
|
return $this->error('Class section not found.', Response::HTTP_NOT_FOUND);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->success(null, 'Class section deleted.');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function attendance(Request $request, int $classSectionId): JsonResponse
|
||||||
|
{
|
||||||
|
$teacherId = (int) ($request->user()?->id ?? 0);
|
||||||
|
if ($teacherId <= 0) {
|
||||||
|
return $this->error('Missing teacher authentication.', Response::HTTP_UNAUTHORIZED);
|
||||||
|
}
|
||||||
|
|
||||||
|
$payload = $this->attendanceService->getAttendancePayload(
|
||||||
|
$classSectionId,
|
||||||
|
$teacherId,
|
||||||
|
$request->query('school_year'),
|
||||||
|
$request->query('semester')
|
||||||
|
);
|
||||||
|
|
||||||
|
if (empty($payload['students'])) {
|
||||||
|
return $this->error('No data found for this class.', Response::HTTP_NOT_FOUND);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->success([
|
||||||
|
'attendance' => new ClassAttendanceResource($payload),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function seedDefaults(): JsonResponse
|
||||||
|
{
|
||||||
|
$this->authorize('seedDefaults', ClassSection::class);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$created = $this->seedService->seedDefaults();
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
Log::error('Seeding default classes failed: ' . $e->getMessage());
|
||||||
|
return $this->error('Unable to seed default classes.', Response::HTTP_INTERNAL_SERVER_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->success([
|
||||||
|
'created' => $created,
|
||||||
|
], 'Default classes seeded.');
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -34,7 +34,8 @@ class PaypalPaymentController extends BaseApiController
|
|||||||
$payload = $request->validated();
|
$payload = $request->validated();
|
||||||
$this->service->executePayment(
|
$this->service->executePayment(
|
||||||
(string) $payload['payer_id'],
|
(string) $payload['payer_id'],
|
||||||
$payload['paypal_payment_id'] ?? null
|
$payload['paypal_payment_id'] ?? null,
|
||||||
|
isset($payload['payment_id']) ? (int) $payload['payment_id'] : null
|
||||||
);
|
);
|
||||||
|
|
||||||
return response()->json(['ok' => true]);
|
return response()->json(['ok' => true]);
|
||||||
|
|||||||
@@ -0,0 +1,72 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Api\Frontend;
|
||||||
|
|
||||||
|
use App\Http\Controllers\Api\BaseApiController;
|
||||||
|
use App\Http\Resources\Frontend\FrontendPageResource;
|
||||||
|
use App\Http\Resources\Frontend\FrontendUserResource;
|
||||||
|
use App\Services\Frontend\FrontendPageService;
|
||||||
|
use Illuminate\Http\JsonResponse;
|
||||||
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
|
|
||||||
|
class FrontendController extends BaseApiController
|
||||||
|
{
|
||||||
|
public function __construct(private FrontendPageService $pageService)
|
||||||
|
{
|
||||||
|
parent::__construct();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function index(): JsonResponse
|
||||||
|
{
|
||||||
|
return $this->success([
|
||||||
|
'page' => new FrontendPageResource($this->pageService->page('index')),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function facility(): JsonResponse
|
||||||
|
{
|
||||||
|
return $this->success([
|
||||||
|
'page' => new FrontendPageResource($this->pageService->page('facility')),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function team(): JsonResponse
|
||||||
|
{
|
||||||
|
return $this->success([
|
||||||
|
'page' => new FrontendPageResource($this->pageService->page('team')),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function callToAction(): JsonResponse
|
||||||
|
{
|
||||||
|
return $this->success([
|
||||||
|
'page' => new FrontendPageResource($this->pageService->page('call_to_action')),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testimonial(): JsonResponse
|
||||||
|
{
|
||||||
|
return $this->success([
|
||||||
|
'page' => new FrontendPageResource($this->pageService->page('testimonial')),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function notFound(): JsonResponse
|
||||||
|
{
|
||||||
|
return $this->success([
|
||||||
|
'page' => new FrontendPageResource($this->pageService->page('not_found')),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function fetchUser(): JsonResponse
|
||||||
|
{
|
||||||
|
$user = auth()->user();
|
||||||
|
if (!$user) {
|
||||||
|
return $this->error('Unauthorized.', Response::HTTP_UNAUTHORIZED);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->success([
|
||||||
|
'user' => new FrontendUserResource($user),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Api\Frontend;
|
||||||
|
|
||||||
|
use App\Http\Controllers\Api\BaseApiController;
|
||||||
|
use App\Http\Resources\Frontend\ProfileIconResource;
|
||||||
|
use App\Services\Frontend\ProfileIconService;
|
||||||
|
use Illuminate\Http\JsonResponse;
|
||||||
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
|
|
||||||
|
class InfoIconController extends BaseApiController
|
||||||
|
{
|
||||||
|
public function __construct(private ProfileIconService $service)
|
||||||
|
{
|
||||||
|
parent::__construct();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function profileIcon(): JsonResponse
|
||||||
|
{
|
||||||
|
$userId = (int) (auth()->id() ?? 0);
|
||||||
|
if ($userId <= 0) {
|
||||||
|
return $this->error('Unauthorized.', Response::HTTP_UNAUTHORIZED);
|
||||||
|
}
|
||||||
|
|
||||||
|
$payload = $this->service->buildForUser($userId);
|
||||||
|
|
||||||
|
return $this->success([
|
||||||
|
'profile' => new ProfileIconResource($payload),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,86 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Api\Frontend;
|
||||||
|
|
||||||
|
use App\Http\Controllers\Api\BaseApiController;
|
||||||
|
use App\Http\Requests\Frontend\LandingTeacherRequest;
|
||||||
|
use App\Http\Resources\Frontend\LandingPageResource;
|
||||||
|
use App\Services\Frontend\LandingPageService;
|
||||||
|
use Illuminate\Http\JsonResponse;
|
||||||
|
|
||||||
|
class LandingPageController extends BaseApiController
|
||||||
|
{
|
||||||
|
public function __construct(private LandingPageService $service)
|
||||||
|
{
|
||||||
|
parent::__construct();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function index(LandingTeacherRequest $request): JsonResponse
|
||||||
|
{
|
||||||
|
$payload = $this->service->dashboardForUser(
|
||||||
|
$request->user(),
|
||||||
|
$request->validated()['class_section_id'] ?? null
|
||||||
|
);
|
||||||
|
|
||||||
|
return $this->success([
|
||||||
|
'landing' => new LandingPageResource($payload),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function teacher(LandingTeacherRequest $request): JsonResponse
|
||||||
|
{
|
||||||
|
$payload = $this->service->teacher(
|
||||||
|
$request->user(),
|
||||||
|
$request->validated()['class_section_id'] ?? null
|
||||||
|
);
|
||||||
|
|
||||||
|
return $this->success([
|
||||||
|
'landing' => new LandingPageResource($payload),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function parent(): JsonResponse
|
||||||
|
{
|
||||||
|
$payload = $this->service->parent(auth()->user());
|
||||||
|
|
||||||
|
return $this->success([
|
||||||
|
'landing' => new LandingPageResource($payload),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function administrator(): JsonResponse
|
||||||
|
{
|
||||||
|
$payload = $this->service->administrator();
|
||||||
|
|
||||||
|
return $this->success([
|
||||||
|
'landing' => new LandingPageResource($payload),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function admin(): JsonResponse
|
||||||
|
{
|
||||||
|
$payload = $this->service->admin();
|
||||||
|
|
||||||
|
return $this->success([
|
||||||
|
'landing' => new LandingPageResource($payload),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function student(): JsonResponse
|
||||||
|
{
|
||||||
|
$payload = $this->service->student();
|
||||||
|
|
||||||
|
return $this->success([
|
||||||
|
'landing' => new LandingPageResource($payload),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function guest(): JsonResponse
|
||||||
|
{
|
||||||
|
$payload = $this->service->guest();
|
||||||
|
|
||||||
|
return $this->success([
|
||||||
|
'landing' => new LandingPageResource($payload),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Api\Frontend;
|
||||||
|
|
||||||
|
use App\Http\Controllers\Api\BaseApiController;
|
||||||
|
use App\Http\Requests\Frontend\ContactSubmitRequest;
|
||||||
|
use App\Http\Resources\Frontend\ContactSubmissionResource;
|
||||||
|
use App\Http\Resources\Frontend\PageContentResource;
|
||||||
|
use App\Services\Frontend\ContactSubmissionService;
|
||||||
|
use App\Services\Frontend\StaticPageService;
|
||||||
|
use Illuminate\Http\JsonResponse;
|
||||||
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
|
|
||||||
|
class PageController extends BaseApiController
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
private StaticPageService $pageService,
|
||||||
|
private ContactSubmissionService $contactService
|
||||||
|
) {
|
||||||
|
parent::__construct();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function privacyPolicy(): JsonResponse
|
||||||
|
{
|
||||||
|
return $this->renderStatic('privacy_policy.html', 'privacy_policy');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function termsOfService(): JsonResponse
|
||||||
|
{
|
||||||
|
return $this->renderStatic('terms_of_service.html', 'terms_of_service');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function helpCenter(): JsonResponse
|
||||||
|
{
|
||||||
|
return $this->renderStatic('help_center.html', 'help_center');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function submitContact(ContactSubmitRequest $request): JsonResponse
|
||||||
|
{
|
||||||
|
$result = $this->contactService->submit($request->validated());
|
||||||
|
|
||||||
|
return $this->success([
|
||||||
|
'submission' => new ContactSubmissionResource([
|
||||||
|
'email' => $request->validated('email'),
|
||||||
|
'email_sent' => $result['email_sent'],
|
||||||
|
'contact_id' => $result['record']?->id,
|
||||||
|
]),
|
||||||
|
], 'Message received.', Response::HTTP_CREATED);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function renderStatic(string $filename, string $type): JsonResponse
|
||||||
|
{
|
||||||
|
$result = $this->pageService->load($filename, $type);
|
||||||
|
if (!$result['ok']) {
|
||||||
|
return $this->error($result['error'], Response::HTTP_NOT_FOUND);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->success([
|
||||||
|
'page' => new PageContentResource($result),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,222 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Api\Messaging;
|
||||||
|
|
||||||
|
use App\Http\Controllers\Api\BaseApiController;
|
||||||
|
use App\Http\Requests\Messaging\MessageIndexRequest;
|
||||||
|
use App\Http\Requests\Messaging\MessageSendRequest;
|
||||||
|
use App\Http\Requests\Messaging\MessageUpdateRequest;
|
||||||
|
use App\Http\Resources\Messaging\MessageCollection;
|
||||||
|
use App\Http\Resources\Messaging\MessageResource;
|
||||||
|
use App\Http\Resources\Messaging\RecipientResource;
|
||||||
|
use App\Models\Message;
|
||||||
|
use App\Services\Messaging\MessageCommandService;
|
||||||
|
use App\Services\Messaging\MessageQueryService;
|
||||||
|
use App\Services\Messaging\MessageRecipientService;
|
||||||
|
use Illuminate\Http\JsonResponse;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
|
|
||||||
|
class MessagesController extends BaseApiController
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
private MessageQueryService $queryService,
|
||||||
|
private MessageCommandService $commandService,
|
||||||
|
private MessageRecipientService $recipientService
|
||||||
|
) {
|
||||||
|
parent::__construct();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function index(MessageIndexRequest $request): JsonResponse
|
||||||
|
{
|
||||||
|
$userId = (int) (auth()->id() ?? 0);
|
||||||
|
if ($userId <= 0) {
|
||||||
|
return $this->error('Unauthorized.', Response::HTTP_UNAUTHORIZED);
|
||||||
|
}
|
||||||
|
|
||||||
|
$filters = $request->validated();
|
||||||
|
$page = (int) ($filters['page'] ?? 1);
|
||||||
|
$perPage = (int) ($filters['per_page'] ?? 20);
|
||||||
|
|
||||||
|
$this->authorize('viewAny', Message::class);
|
||||||
|
|
||||||
|
$role = $this->queryService->getUserRoleName($userId);
|
||||||
|
$messages = $this->queryService->inbox($userId, $filters, $page, $perPage);
|
||||||
|
$collection = new MessageCollection($messages);
|
||||||
|
$meta = $collection->with($request)['meta'] ?? null;
|
||||||
|
|
||||||
|
return $this->success([
|
||||||
|
'role' => $role,
|
||||||
|
'messages' => $collection->toArray($request),
|
||||||
|
'meta' => $meta,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function inbox(MessageIndexRequest $request): JsonResponse
|
||||||
|
{
|
||||||
|
return $this->listMessages($request, 'inbox');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function sent(MessageIndexRequest $request): JsonResponse
|
||||||
|
{
|
||||||
|
return $this->listMessages($request, 'sent');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function drafts(MessageIndexRequest $request): JsonResponse
|
||||||
|
{
|
||||||
|
return $this->listMessages($request, 'drafts');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function trash(MessageIndexRequest $request): JsonResponse
|
||||||
|
{
|
||||||
|
return $this->listMessages($request, 'trash');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function show(int $id): JsonResponse
|
||||||
|
{
|
||||||
|
$message = $this->queryService->findForUser($id);
|
||||||
|
if (!$message) {
|
||||||
|
return $this->error('Message not found.', Response::HTTP_NOT_FOUND);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->authorize('view', $message);
|
||||||
|
|
||||||
|
$userId = (int) (auth()->id() ?? 0);
|
||||||
|
if ($message->recipient_id === $userId) {
|
||||||
|
$this->commandService->markRead($message);
|
||||||
|
$message->refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->success([
|
||||||
|
'message' => new MessageResource($message),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function store(MessageSendRequest $request): JsonResponse
|
||||||
|
{
|
||||||
|
$userId = (int) (auth()->id() ?? 0);
|
||||||
|
if ($userId <= 0) {
|
||||||
|
return $this->error('Unauthorized.', Response::HTTP_UNAUTHORIZED);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->authorize('create', Message::class);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$message = $this->commandService->create($userId, $request->validated(), $request->file('attachment'));
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
Log::error('Message send failed: ' . $e->getMessage());
|
||||||
|
return $this->error($e->getMessage(), Response::HTTP_BAD_REQUEST);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->success([
|
||||||
|
'message' => new MessageResource($message->fresh(['sender', 'recipient'])),
|
||||||
|
], 'Message sent.', Response::HTTP_CREATED);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function receive(): JsonResponse
|
||||||
|
{
|
||||||
|
$userId = (int) (auth()->id() ?? 0);
|
||||||
|
if ($userId <= 0) {
|
||||||
|
return $this->error('Unauthorized.', Response::HTTP_UNAUTHORIZED);
|
||||||
|
}
|
||||||
|
|
||||||
|
$messages = $this->queryService->receivedAndMarkRead($userId);
|
||||||
|
|
||||||
|
return $this->success([
|
||||||
|
'messages' => (new MessageCollection(collect($messages)))->toArray(request()),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function recipients(string $type): JsonResponse
|
||||||
|
{
|
||||||
|
$type = strtolower(trim($type));
|
||||||
|
$data = match ($type) {
|
||||||
|
'teacher' => $this->recipientService->teachers(),
|
||||||
|
'parent' => $this->recipientService->parents(),
|
||||||
|
default => null,
|
||||||
|
};
|
||||||
|
|
||||||
|
if ($data === null) {
|
||||||
|
return $this->error('Invalid recipient type.', Response::HTTP_BAD_REQUEST);
|
||||||
|
}
|
||||||
|
|
||||||
|
$payload = array_map(fn ($row) => (new RecipientResource($row))->toArray(request()), $data);
|
||||||
|
|
||||||
|
return $this->success([
|
||||||
|
'recipients' => $payload,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function update(MessageUpdateRequest $request, int $id): JsonResponse
|
||||||
|
{
|
||||||
|
$message = Message::query()->find($id);
|
||||||
|
if (!$message) {
|
||||||
|
return $this->error('Message not found.', Response::HTTP_NOT_FOUND);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->authorize('update', $message);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$updated = $this->commandService->update($message, $request->validated());
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
Log::error('Message update failed: ' . $e->getMessage());
|
||||||
|
return $this->error('Unable to update message.', Response::HTTP_INTERNAL_SERVER_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->success([
|
||||||
|
'message' => new MessageResource($updated->load(['sender', 'recipient'])),
|
||||||
|
], 'Message updated.');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function destroy(int $id): JsonResponse
|
||||||
|
{
|
||||||
|
$message = Message::query()->find($id);
|
||||||
|
if (!$message) {
|
||||||
|
return $this->error('Message not found.', Response::HTTP_NOT_FOUND);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->authorize('delete', $message);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$trashed = $this->commandService->trash($message);
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
Log::error('Message delete failed: ' . $e->getMessage());
|
||||||
|
return $this->error('Unable to delete message.', Response::HTTP_INTERNAL_SERVER_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$trashed) {
|
||||||
|
return $this->error('Unable to delete message.', Response::HTTP_INTERNAL_SERVER_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->success(null, 'Message deleted.');
|
||||||
|
}
|
||||||
|
|
||||||
|
private function listMessages(MessageIndexRequest $request, string $bucket): JsonResponse
|
||||||
|
{
|
||||||
|
$userId = (int) (auth()->id() ?? 0);
|
||||||
|
if ($userId <= 0) {
|
||||||
|
return $this->error('Unauthorized.', Response::HTTP_UNAUTHORIZED);
|
||||||
|
}
|
||||||
|
|
||||||
|
$filters = $request->validated();
|
||||||
|
$page = (int) ($filters['page'] ?? 1);
|
||||||
|
$perPage = (int) ($filters['per_page'] ?? 20);
|
||||||
|
|
||||||
|
$this->authorize('viewAny', Message::class);
|
||||||
|
|
||||||
|
$paginator = match ($bucket) {
|
||||||
|
'sent' => $this->queryService->sent($userId, $filters, $page, $perPage),
|
||||||
|
'drafts' => $this->queryService->drafts($userId, $filters, $page, $perPage),
|
||||||
|
'trash' => $this->queryService->trash($userId, $filters, $page, $perPage),
|
||||||
|
default => $this->queryService->inbox($userId, $filters, $page, $perPage),
|
||||||
|
};
|
||||||
|
|
||||||
|
$collection = new MessageCollection($paginator);
|
||||||
|
$meta = $collection->with($request)['meta'] ?? null;
|
||||||
|
|
||||||
|
return $this->success([
|
||||||
|
'messages' => $collection->toArray($request),
|
||||||
|
'meta' => $meta,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Api\Settings;
|
||||||
|
|
||||||
|
use App\Http\Controllers\Api\BaseApiController;
|
||||||
|
use App\Http\Requests\Settings\PolicyShowRequest;
|
||||||
|
use App\Http\Resources\Settings\PolicyResource;
|
||||||
|
use App\Services\Policy\PolicyContentService;
|
||||||
|
use Illuminate\Http\JsonResponse;
|
||||||
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
|
|
||||||
|
class PolicyController extends BaseApiController
|
||||||
|
{
|
||||||
|
public function __construct(private PolicyContentService $service)
|
||||||
|
{
|
||||||
|
parent::__construct();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function school(PolicyShowRequest $request): JsonResponse
|
||||||
|
{
|
||||||
|
return $this->respondPolicy('school');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function picture(PolicyShowRequest $request): JsonResponse
|
||||||
|
{
|
||||||
|
return $this->respondPolicy('picture');
|
||||||
|
}
|
||||||
|
|
||||||
|
private function respondPolicy(string $type): JsonResponse
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$policy = $this->service->getPolicy($type);
|
||||||
|
} catch (\InvalidArgumentException $e) {
|
||||||
|
return $this->error('Policy not found.', Response::HTTP_NOT_FOUND);
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
return $this->error('Unable to load policy.', Response::HTTP_INTERNAL_SERVER_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->success([
|
||||||
|
'policy' => new PolicyResource($policy),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,139 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Api\Settings;
|
||||||
|
|
||||||
|
use App\Http\Controllers\Api\BaseApiController;
|
||||||
|
use App\Http\Requests\Preferences\PreferencesIndexRequest;
|
||||||
|
use App\Http\Requests\Preferences\PreferencesUpsertRequest;
|
||||||
|
use App\Http\Resources\Preferences\PreferencesCollection;
|
||||||
|
use App\Http\Resources\Preferences\PreferencesResource;
|
||||||
|
use App\Models\Preferences;
|
||||||
|
use App\Services\Preferences\PreferencesCommandService;
|
||||||
|
use App\Services\Preferences\PreferencesQueryService;
|
||||||
|
use Illuminate\Http\JsonResponse;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
|
|
||||||
|
class PreferencesController extends BaseApiController
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
private PreferencesQueryService $queryService,
|
||||||
|
private PreferencesCommandService $commandService
|
||||||
|
) {
|
||||||
|
parent::__construct();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function index(PreferencesIndexRequest $request): JsonResponse
|
||||||
|
{
|
||||||
|
$this->authorize('viewAny', Preferences::class);
|
||||||
|
|
||||||
|
$filters = $request->validated();
|
||||||
|
$page = (int) ($filters['page'] ?? 1);
|
||||||
|
$perPage = (int) ($filters['per_page'] ?? 20);
|
||||||
|
|
||||||
|
$rows = $this->queryService->paginate($filters, $page, $perPage);
|
||||||
|
$collection = new PreferencesCollection($rows);
|
||||||
|
|
||||||
|
return $this->success([
|
||||||
|
'preferences' => $collection->toArray($request),
|
||||||
|
'meta' => $collection->with($request)['meta'],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function show(): JsonResponse
|
||||||
|
{
|
||||||
|
$userId = (int) (auth()->id() ?? 0);
|
||||||
|
if ($userId <= 0) {
|
||||||
|
return $this->error('Unauthorized.', Response::HTTP_UNAUTHORIZED);
|
||||||
|
}
|
||||||
|
|
||||||
|
$payload = $this->queryService->getForUser($userId);
|
||||||
|
|
||||||
|
return $this->success([
|
||||||
|
'preferences' => new PreferencesResource($payload['preferences']),
|
||||||
|
'options' => $payload['options'],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function showForUser(int $userId): JsonResponse
|
||||||
|
{
|
||||||
|
$row = Preferences::query()->where('user_id', $userId)->first();
|
||||||
|
if (!$row) {
|
||||||
|
return $this->error('Preferences not found.', Response::HTTP_NOT_FOUND);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->authorize('view', $row);
|
||||||
|
|
||||||
|
$payload = $this->queryService->getForUser($userId);
|
||||||
|
|
||||||
|
return $this->success([
|
||||||
|
'preferences' => new PreferencesResource($payload['preferences']),
|
||||||
|
'options' => $payload['options'],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function store(PreferencesUpsertRequest $request): JsonResponse
|
||||||
|
{
|
||||||
|
$userId = (int) (auth()->id() ?? 0);
|
||||||
|
if ($userId <= 0) {
|
||||||
|
return $this->error('Unauthorized.', Response::HTTP_UNAUTHORIZED);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
$saved = $this->commandService->upsert($userId, $request->validated());
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
Log::error('Preferences save failed: ' . $e->getMessage());
|
||||||
|
return $this->error('Unable to save preferences.', Response::HTTP_INTERNAL_SERVER_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
$payload = $this->queryService->getForUser($userId);
|
||||||
|
|
||||||
|
return $this->success([
|
||||||
|
'preferences' => new PreferencesResource($payload['preferences']),
|
||||||
|
], 'Preferences saved.', $saved->wasRecentlyCreated ? Response::HTTP_CREATED : Response::HTTP_OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function updateForUser(PreferencesUpsertRequest $request, int $userId): JsonResponse
|
||||||
|
{
|
||||||
|
$row = Preferences::query()->where('user_id', $userId)->first();
|
||||||
|
if ($row) {
|
||||||
|
$this->authorize('update', $row);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
$saved = $this->commandService->upsert($userId, $request->validated());
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
Log::error('Preferences update failed: ' . $e->getMessage());
|
||||||
|
return $this->error('Unable to save preferences.', Response::HTTP_INTERNAL_SERVER_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
$payload = $this->queryService->getForUser($userId);
|
||||||
|
|
||||||
|
return $this->success([
|
||||||
|
'preferences' => new PreferencesResource($payload['preferences']),
|
||||||
|
], 'Preferences saved.', $saved->wasRecentlyCreated ? Response::HTTP_CREATED : Response::HTTP_OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function destroy(int $userId): JsonResponse
|
||||||
|
{
|
||||||
|
$row = Preferences::query()->where('user_id', $userId)->first();
|
||||||
|
if (!$row) {
|
||||||
|
return $this->error('Preferences not found.', Response::HTTP_NOT_FOUND);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->authorize('delete', $row);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$deleted = $this->commandService->delete($row);
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
Log::error('Preferences delete failed: ' . $e->getMessage());
|
||||||
|
return $this->error('Unable to delete preferences.', Response::HTTP_INTERNAL_SERVER_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$deleted) {
|
||||||
|
return $this->error('Unable to delete preferences.', Response::HTTP_INTERNAL_SERVER_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->success(null, 'Preferences deleted.');
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Api\Settings;
|
||||||
|
|
||||||
|
use App\Http\Controllers\Api\BaseApiController;
|
||||||
|
use App\Http\Requests\Settings\SettingsUpdateRequest;
|
||||||
|
use App\Http\Resources\Settings\SettingsResource;
|
||||||
|
use App\Models\Setting;
|
||||||
|
use App\Services\Settings\SettingsService;
|
||||||
|
use Illuminate\Http\JsonResponse;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
|
|
||||||
|
class SettingsController extends BaseApiController
|
||||||
|
{
|
||||||
|
public function __construct(private SettingsService $settingsService)
|
||||||
|
{
|
||||||
|
parent::__construct();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function index(): JsonResponse
|
||||||
|
{
|
||||||
|
$this->authorize('viewAny', Setting::class);
|
||||||
|
|
||||||
|
return $this->success([
|
||||||
|
'settings' => new SettingsResource($this->settingsService->get()),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function update(SettingsUpdateRequest $request): JsonResponse
|
||||||
|
{
|
||||||
|
$settings = Setting::singleton();
|
||||||
|
$this->authorize('update', $settings);
|
||||||
|
|
||||||
|
$userId = (int) (auth()->id() ?? 0);
|
||||||
|
if ($userId <= 0) {
|
||||||
|
return $this->error('Unauthorized.', Response::HTTP_UNAUTHORIZED);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
$updated = $this->settingsService->update($request->validated(), $userId);
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
Log::error('Settings update failed: ' . $e->getMessage());
|
||||||
|
return $this->error('Unable to update settings.', Response::HTTP_INTERNAL_SERVER_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->success([
|
||||||
|
'settings' => new SettingsResource($updated),
|
||||||
|
], 'Settings updated.');
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,121 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Api\Staff;
|
||||||
|
|
||||||
|
use App\Http\Controllers\Api\BaseApiController;
|
||||||
|
use App\Http\Requests\Staff\StaffIndexRequest;
|
||||||
|
use App\Http\Requests\Staff\StaffStoreRequest;
|
||||||
|
use App\Http\Requests\Staff\StaffUpdateRequest;
|
||||||
|
use App\Http\Resources\Staff\StaffCollection;
|
||||||
|
use App\Http\Resources\Staff\StaffResource;
|
||||||
|
use App\Models\Staff;
|
||||||
|
use App\Services\Staff\StaffCommandService;
|
||||||
|
use App\Services\Staff\StaffQueryService;
|
||||||
|
use Illuminate\Http\JsonResponse;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
|
|
||||||
|
class StaffController extends BaseApiController
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
private StaffQueryService $queryService,
|
||||||
|
private StaffCommandService $commandService
|
||||||
|
) {
|
||||||
|
parent::__construct();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function index(StaffIndexRequest $request): JsonResponse
|
||||||
|
{
|
||||||
|
$this->authorize('viewAny', Staff::class);
|
||||||
|
|
||||||
|
$filters = $request->validated();
|
||||||
|
$page = (int) ($filters['page'] ?? 1);
|
||||||
|
$perPage = (int) ($filters['per_page'] ?? 20);
|
||||||
|
|
||||||
|
$result = $this->queryService->paginate($filters, $page, $perPage);
|
||||||
|
$collection = new StaffCollection($result['paginator']);
|
||||||
|
|
||||||
|
return $this->success([
|
||||||
|
'staff' => $collection->toArray($request),
|
||||||
|
'meta' => $collection->with($request)['meta'] ?? null,
|
||||||
|
'issues_count' => $result['issues_count'],
|
||||||
|
'semester' => $result['semester'],
|
||||||
|
'school_year' => $result['school_year'],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function show(int $id): JsonResponse
|
||||||
|
{
|
||||||
|
$staff = $this->queryService->find($id);
|
||||||
|
if (!$staff) {
|
||||||
|
return $this->error('Staff member not found.', Response::HTTP_NOT_FOUND);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->authorize('view', $staff);
|
||||||
|
$staff->school_id = \App\Models\User::getSchoolIdByUserId((int) ($staff->user_id ?? 0));
|
||||||
|
|
||||||
|
return $this->success([
|
||||||
|
'staff' => new StaffResource($staff),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function store(StaffStoreRequest $request): JsonResponse
|
||||||
|
{
|
||||||
|
$this->authorize('create', Staff::class);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$staff = $this->commandService->create($request->validated());
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
Log::error('Staff create failed: ' . $e->getMessage());
|
||||||
|
return $this->error($e->getMessage(), Response::HTTP_BAD_REQUEST);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->success([
|
||||||
|
'staff' => new StaffResource($staff),
|
||||||
|
], 'Staff member added.', Response::HTTP_CREATED);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function update(StaffUpdateRequest $request, int $id): JsonResponse
|
||||||
|
{
|
||||||
|
$staff = $this->queryService->find($id);
|
||||||
|
if (!$staff) {
|
||||||
|
return $this->error('Staff member not found.', Response::HTTP_NOT_FOUND);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->authorize('update', $staff);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$updated = $this->commandService->update($staff, $request->validated());
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
Log::error('Staff update failed: ' . $e->getMessage());
|
||||||
|
return $this->error('Unable to update staff.', Response::HTTP_INTERNAL_SERVER_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->success([
|
||||||
|
'staff' => new StaffResource($updated),
|
||||||
|
], 'Staff member updated.');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function destroy(int $id): JsonResponse
|
||||||
|
{
|
||||||
|
$staff = $this->queryService->find($id);
|
||||||
|
if (!$staff) {
|
||||||
|
return $this->error('Staff member not found.', Response::HTTP_NOT_FOUND);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->authorize('delete', $staff);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$deleted = $this->commandService->delete($staff);
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
Log::error('Staff delete failed: ' . $e->getMessage());
|
||||||
|
return $this->error('Unable to delete staff.', Response::HTTP_INTERNAL_SERVER_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$deleted) {
|
||||||
|
return $this->error('Unable to delete staff.', Response::HTTP_INTERNAL_SERVER_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->success(null, 'Staff member deleted.');
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Api\Support;
|
||||||
|
|
||||||
|
use App\Http\Controllers\Api\BaseApiController;
|
||||||
|
use App\Http\Requests\Support\ContactSendRequest;
|
||||||
|
use App\Http\Resources\Support\ContactMessageResource;
|
||||||
|
use App\Services\Support\ContactMessageService;
|
||||||
|
use Illuminate\Http\JsonResponse;
|
||||||
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
|
|
||||||
|
class ContactController extends BaseApiController
|
||||||
|
{
|
||||||
|
public function __construct(private ContactMessageService $messageService)
|
||||||
|
{
|
||||||
|
parent::__construct();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function send(ContactSendRequest $request): JsonResponse
|
||||||
|
{
|
||||||
|
$result = $this->messageService->send($request->validated());
|
||||||
|
|
||||||
|
return $this->success([
|
||||||
|
'contact' => new ContactMessageResource($result),
|
||||||
|
], 'Message sent.', Response::HTTP_CREATED);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,83 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Api\Support;
|
||||||
|
|
||||||
|
use App\Http\Controllers\Api\BaseApiController;
|
||||||
|
use App\Http\Requests\Support\SupportRequestIndexRequest;
|
||||||
|
use App\Http\Requests\Support\SupportRequestStoreRequest;
|
||||||
|
use App\Http\Resources\Support\SupportRequestCollection;
|
||||||
|
use App\Http\Resources\Support\SupportRequestResource;
|
||||||
|
use App\Models\SupportRequest;
|
||||||
|
use App\Services\Support\SupportRequestService;
|
||||||
|
use Illuminate\Http\JsonResponse;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
|
|
||||||
|
class SupportController extends BaseApiController
|
||||||
|
{
|
||||||
|
public function __construct(private SupportRequestService $supportService)
|
||||||
|
{
|
||||||
|
parent::__construct();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function index(SupportRequestIndexRequest $request): JsonResponse
|
||||||
|
{
|
||||||
|
$userId = (int) (auth()->id() ?? 0);
|
||||||
|
if ($userId <= 0) {
|
||||||
|
return $this->error('Unauthorized.', Response::HTTP_UNAUTHORIZED);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->authorize('viewAny', SupportRequest::class);
|
||||||
|
|
||||||
|
$filters = $request->validated();
|
||||||
|
$page = (int) ($filters['page'] ?? 1);
|
||||||
|
$perPage = (int) ($filters['per_page'] ?? 20);
|
||||||
|
|
||||||
|
$isAdmin = auth()->user()?->roles()
|
||||||
|
->pluck('roles.name')
|
||||||
|
->map(fn ($name) => strtolower((string) $name))
|
||||||
|
->intersect(['administrator', 'admin', 'principal', 'vice_principal', 'vice-principal'])
|
||||||
|
->isNotEmpty();
|
||||||
|
|
||||||
|
$paginator = $this->supportService->list($userId, $filters, $page, $perPage, $isAdmin);
|
||||||
|
$collection = new SupportRequestCollection($paginator);
|
||||||
|
|
||||||
|
return $this->success([
|
||||||
|
'requests' => $collection->toArray($request),
|
||||||
|
'meta' => $collection->with($request)['meta'] ?? null,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function store(SupportRequestStoreRequest $request): JsonResponse
|
||||||
|
{
|
||||||
|
$user = auth()->user();
|
||||||
|
if (!$user) {
|
||||||
|
return $this->error('Unauthorized.', Response::HTTP_UNAUTHORIZED);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->authorize('create', SupportRequest::class);
|
||||||
|
|
||||||
|
$payload = $request->validated();
|
||||||
|
$payload['user_email'] = $user->email ?? null;
|
||||||
|
$payload['user_name'] = trim(($user->firstname ?? '') . ' ' . ($user->lastname ?? ''));
|
||||||
|
|
||||||
|
try {
|
||||||
|
$result = $this->supportService->create($user->id, $payload);
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
Log::error('Support request failed: ' . $e->getMessage());
|
||||||
|
return $this->error('Unable to submit support request.', Response::HTTP_INTERNAL_SERVER_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->success([
|
||||||
|
'request' => new SupportRequestResource($result['record']),
|
||||||
|
'email_sent' => $result['email_sent'],
|
||||||
|
], 'Support request submitted.', Response::HTTP_CREATED);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function teacher(): JsonResponse
|
||||||
|
{
|
||||||
|
return $this->success([
|
||||||
|
'page' => 'teacher_support',
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Api\System;
|
||||||
|
|
||||||
|
use App\Http\Controllers\Api\BaseApiController;
|
||||||
|
use App\Http\Resources\System\DashboardRouteResource;
|
||||||
|
use App\Services\Dashboard\DashboardRouteService;
|
||||||
|
use Illuminate\Http\JsonResponse;
|
||||||
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
|
|
||||||
|
class DashboardController extends BaseApiController
|
||||||
|
{
|
||||||
|
public function __construct(private DashboardRouteService $service)
|
||||||
|
{
|
||||||
|
parent::__construct();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function route(): JsonResponse
|
||||||
|
{
|
||||||
|
$user = auth()->user();
|
||||||
|
if (!$user) {
|
||||||
|
return $this->error('Unauthorized.', Response::HTTP_UNAUTHORIZED);
|
||||||
|
}
|
||||||
|
|
||||||
|
$payload = $this->service->resolveForUser($user);
|
||||||
|
|
||||||
|
return $this->success([
|
||||||
|
'dashboard' => new DashboardRouteResource($payload),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Api\System;
|
||||||
|
|
||||||
|
use App\Http\Controllers\Api\BaseApiController;
|
||||||
|
use App\Services\System\DatabaseHealthService;
|
||||||
|
use Illuminate\Http\JsonResponse;
|
||||||
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
|
|
||||||
|
class DatabaseHealthController extends BaseApiController
|
||||||
|
{
|
||||||
|
public function __construct(private DatabaseHealthService $healthService)
|
||||||
|
{
|
||||||
|
parent::__construct();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function index(): JsonResponse
|
||||||
|
{
|
||||||
|
$result = $this->healthService->check();
|
||||||
|
if (!$result['ok']) {
|
||||||
|
return $this->error('Database connection failed.', Response::HTTP_SERVICE_UNAVAILABLE, [
|
||||||
|
'error' => $result['error'],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->success([
|
||||||
|
'ok' => true,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Api\System;
|
||||||
|
|
||||||
|
use App\Http\Controllers\Api\BaseApiController;
|
||||||
|
use App\Http\Resources\System\HealthStatusResource;
|
||||||
|
use App\Services\System\HealthCheckService;
|
||||||
|
use Illuminate\Http\JsonResponse;
|
||||||
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
|
|
||||||
|
class HealthController extends BaseApiController
|
||||||
|
{
|
||||||
|
public function __construct(private HealthCheckService $service)
|
||||||
|
{
|
||||||
|
parent::__construct();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function index(): JsonResponse
|
||||||
|
{
|
||||||
|
$payload = $this->service->check();
|
||||||
|
$status = $payload['ok'] ? Response::HTTP_OK : Response::HTTP_SERVICE_UNAVAILABLE;
|
||||||
|
|
||||||
|
return $this->success([
|
||||||
|
'health' => new HealthStatusResource($payload),
|
||||||
|
], 'Health check.', $status);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,90 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Api\System;
|
||||||
|
|
||||||
|
use App\Http\Controllers\Api\BaseApiController;
|
||||||
|
use App\Http\Requests\System\NavItemReorderRequest;
|
||||||
|
use App\Http\Requests\System\NavItemStoreRequest;
|
||||||
|
use App\Http\Resources\System\NavBuilderDataResource;
|
||||||
|
use App\Http\Resources\System\NavItemResource;
|
||||||
|
use App\Models\NavItem;
|
||||||
|
use App\Services\Navigation\NavBuilderService;
|
||||||
|
use App\Services\Navigation\NavbarService;
|
||||||
|
use Illuminate\Http\JsonResponse;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
|
|
||||||
|
class NavBuilderController extends BaseApiController
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
private NavBuilderService $builderService,
|
||||||
|
private NavbarService $navbarService
|
||||||
|
) {
|
||||||
|
parent::__construct();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function menu(): JsonResponse
|
||||||
|
{
|
||||||
|
$user = auth()->user();
|
||||||
|
$roles = $user?->roles()->pluck('roles.name')->map(fn ($name) => strtolower((string) $name))->toArray() ?? [];
|
||||||
|
|
||||||
|
$menu = $this->navbarService->getMenuForRoles($roles);
|
||||||
|
|
||||||
|
return $this->success([
|
||||||
|
'items' => NavItemResource::collection($menu),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function data(): JsonResponse
|
||||||
|
{
|
||||||
|
$this->authorize('manage', NavItem::class);
|
||||||
|
|
||||||
|
$payload = $this->builderService->getAdminPayload();
|
||||||
|
|
||||||
|
return $this->success([
|
||||||
|
'data' => new NavBuilderDataResource($payload),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function store(NavItemStoreRequest $request): JsonResponse
|
||||||
|
{
|
||||||
|
$this->authorize('manage', NavItem::class);
|
||||||
|
|
||||||
|
$result = $this->builderService->save($request->validated());
|
||||||
|
|
||||||
|
if (empty($result['ok'])) {
|
||||||
|
return $this->error($result['message'] ?? 'Unable to save menu item.', Response::HTTP_UNPROCESSABLE_ENTITY);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->success([
|
||||||
|
'id' => $result['id'],
|
||||||
|
], 'Menu saved.', Response::HTTP_CREATED);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function destroy(int $id): JsonResponse
|
||||||
|
{
|
||||||
|
$this->authorize('manage', NavItem::class);
|
||||||
|
|
||||||
|
$deleted = $this->builderService->delete($id);
|
||||||
|
|
||||||
|
if (!$deleted) {
|
||||||
|
return $this->error('Menu item not found.', Response::HTTP_NOT_FOUND);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->success(null, 'Menu item deleted.');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function reorder(NavItemReorderRequest $request): JsonResponse
|
||||||
|
{
|
||||||
|
$this->authorize('manage', NavItem::class);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$this->builderService->reorder($request->validated()['orders']);
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
Log::error('Nav reorder failed: ' . $e->getMessage());
|
||||||
|
return $this->error('Unable to reorder items.', Response::HTTP_INTERNAL_SERVER_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->success(['ok' => true], 'Menu reordered.');
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Api\Ui;
|
||||||
|
|
||||||
|
use App\Http\Controllers\Api\BaseApiController;
|
||||||
|
use App\Http\Requests\Ui\UiStyleRequest;
|
||||||
|
use App\Http\Resources\Ui\UiStyleResource;
|
||||||
|
use App\Services\Ui\UiStyleService;
|
||||||
|
use Illuminate\Http\JsonResponse;
|
||||||
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
|
|
||||||
|
class UiController extends BaseApiController
|
||||||
|
{
|
||||||
|
public function __construct(private UiStyleService $styleService)
|
||||||
|
{
|
||||||
|
parent::__construct();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function style(UiStyleRequest $request): JsonResponse
|
||||||
|
{
|
||||||
|
$userId = (int) (auth()->id() ?? 0);
|
||||||
|
if ($userId <= 0) {
|
||||||
|
return $this->error('Unauthorized.', Response::HTTP_UNAUTHORIZED);
|
||||||
|
}
|
||||||
|
|
||||||
|
$prefs = $this->styleService->update($userId, $request->validated());
|
||||||
|
|
||||||
|
return $this->success([
|
||||||
|
'preferences' => new UiStyleResource($prefs),
|
||||||
|
], 'Style updated.');
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Api\Utilities;
|
||||||
|
|
||||||
|
use App\Http\Controllers\Api\BaseApiController;
|
||||||
|
use App\Http\Requests\Utilities\PhoneFormatRequest;
|
||||||
|
use App\Http\Resources\Utilities\PhoneFormatResource;
|
||||||
|
use App\Services\Phone\PhoneFormatterService;
|
||||||
|
use Illuminate\Http\JsonResponse;
|
||||||
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
|
|
||||||
|
class PhoneFormatterController extends BaseApiController
|
||||||
|
{
|
||||||
|
public function __construct(private PhoneFormatterService $service)
|
||||||
|
{
|
||||||
|
parent::__construct();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function format(PhoneFormatRequest $request): JsonResponse
|
||||||
|
{
|
||||||
|
$raw = (string) $request->validated()['number'];
|
||||||
|
$formatted = $this->service->format($raw);
|
||||||
|
|
||||||
|
if ($formatted === null) {
|
||||||
|
return $this->error('Invalid phone number.', Response::HTTP_UNPROCESSABLE_ENTITY);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->success([
|
||||||
|
'phone' => new PhoneFormatResource([
|
||||||
|
'raw' => $raw,
|
||||||
|
'formatted' => $formatted,
|
||||||
|
'is_valid' => true,
|
||||||
|
]),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,150 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Http\Controllers\View;
|
|
||||||
|
|
||||||
use App\Http\Controllers\Controller;
|
|
||||||
use App\Models\ClassSection;
|
|
||||||
use App\Models\Configuration;
|
|
||||||
use App\Models\Student;
|
|
||||||
use App\Models\Teacher;
|
|
||||||
use Illuminate\Http\RedirectResponse;
|
|
||||||
use Illuminate\Http\Request;
|
|
||||||
use Illuminate\Support\Facades\DB;
|
|
||||||
use Illuminate\View\View;
|
|
||||||
|
|
||||||
class ClassController extends Controller
|
|
||||||
{
|
|
||||||
protected ClassSection $classSection;
|
|
||||||
protected Student $student;
|
|
||||||
protected Teacher $teacher;
|
|
||||||
protected Configuration $config;
|
|
||||||
protected ?string $semester;
|
|
||||||
protected ?string $schoolYear;
|
|
||||||
|
|
||||||
public function __construct(
|
|
||||||
ClassSection $classSection,
|
|
||||||
Student $student,
|
|
||||||
Teacher $teacher,
|
|
||||||
Configuration $config
|
|
||||||
) {
|
|
||||||
$this->classSection = $classSection;
|
|
||||||
$this->student = $student;
|
|
||||||
$this->teacher = $teacher;
|
|
||||||
$this->config = $config;
|
|
||||||
|
|
||||||
$this->semester = $this->config->getConfig('semester');
|
|
||||||
$this->schoolYear = $this->config->getConfig('school_year');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function index(): View
|
|
||||||
{
|
|
||||||
$classSections = $this->classSection
|
|
||||||
->newQuery()
|
|
||||||
->orderBy('class_section_name', 'ASC')
|
|
||||||
->get();
|
|
||||||
|
|
||||||
return view('administrator.class_section', [
|
|
||||||
'classsection' => $classSections,
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function create(): View
|
|
||||||
{
|
|
||||||
return view('administrator.create_class');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function store(Request $request): RedirectResponse
|
|
||||||
{
|
|
||||||
$data = $request->only(['name', 'description']);
|
|
||||||
// TODO: persist the payload once the backing model/table columns are finalized.
|
|
||||||
|
|
||||||
return redirect()->to('/administrator/classes')->with([
|
|
||||||
'payload' => $data,
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function edit(int $id): View
|
|
||||||
{
|
|
||||||
return view('administrator.edit_class', [
|
|
||||||
'class' => $this->classSection->find($id),
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function updateClass(Request $request, int $id): RedirectResponse
|
|
||||||
{
|
|
||||||
$data = $request->only(['name', 'description']);
|
|
||||||
// TODO: persist the payload once the backing model/table columns are finalized.
|
|
||||||
|
|
||||||
return redirect()->to('/administrator/classes')->with([
|
|
||||||
'payload' => $data,
|
|
||||||
'id' => $id,
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function destroyClass(int $id): RedirectResponse
|
|
||||||
{
|
|
||||||
// TODO: remove the record once the backing model/table columns are finalized.
|
|
||||||
|
|
||||||
return redirect()->to('/administrator/classes')->with([
|
|
||||||
'deleted_id' => $id,
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function addClasses(): RedirectResponse
|
|
||||||
{
|
|
||||||
$classes = [
|
|
||||||
['class_name' => 'Class 1', 'teacher_id' => 1, 'schedule' => 'Monday 9:00 AM - 10:00 AM', 'capacity' => 30],
|
|
||||||
['class_name' => 'Class 2', 'teacher_id' => 2, 'schedule' => 'Tuesday 9:00 AM - 10:00 AM', 'capacity' => 30],
|
|
||||||
['class_name' => 'Class 3', 'teacher_id' => 3, 'schedule' => 'Wednesday 9:00 AM - 10:00 AM', 'capacity' => 30],
|
|
||||||
['class_name' => 'Class 4', 'teacher_id' => 4, 'schedule' => 'Thursday 9:00 AM - 10:00 AM', 'capacity' => 30],
|
|
||||||
['class_name' => 'Class 5', 'teacher_id' => 5, 'schedule' => 'Friday 9:00 AM - 10:00 AM', 'capacity' => 30],
|
|
||||||
['class_name' => 'Class 6', 'teacher_id' => 6, 'schedule' => 'Monday 10:00 AM - 11:00 AM', 'capacity' => 30],
|
|
||||||
['class_name' => 'Class 7', 'teacher_id' => 7, 'schedule' => 'Tuesday 10:00 AM - 11:00 AM', 'capacity' => 30],
|
|
||||||
['class_name' => 'Class 8', 'teacher_id' => 8, 'schedule' => 'Wednesday 10:00 AM - 11:00 AM', 'capacity' => 30],
|
|
||||||
['class_name' => 'Class 9', 'teacher_id' => 9, 'schedule' => 'Thursday 10:00 AM - 11:00 AM', 'capacity' => 30],
|
|
||||||
['class_name' => 'Youth', 'teacher_id' => 10, 'schedule' => 'Friday 10:00 AM - 11:00 AM', 'capacity' => 30],
|
|
||||||
];
|
|
||||||
|
|
||||||
DB::transaction(function () use ($classes) {
|
|
||||||
foreach ($classes as $class) {
|
|
||||||
DB::table('classes')->insert($class);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return redirect()->to('/parent/classes')->with('success', 'Classes added successfully.');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function classAttendance(int $classSectionId): RedirectResponse|View
|
|
||||||
{
|
|
||||||
$teacherId = (int) (session()->get('user_id') ?? 0);
|
|
||||||
if ($teacherId <= 0) {
|
|
||||||
return redirect()->to('/teacher/classes')->with('error', 'Missing teacher session.');
|
|
||||||
}
|
|
||||||
|
|
||||||
$teacherData = $this->teacher->find($teacherId);
|
|
||||||
|
|
||||||
$studentsData = $this->student->newQuery()
|
|
||||||
->join('student_class', 'students.id', '=', 'student_class.student_id')
|
|
||||||
->leftJoin('class_sections', 'class_sections.id', '=', 'student_class.class_section_id')
|
|
||||||
->where('student_class.class_section_id', $classSectionId)
|
|
||||||
->select('students.*', 'student_class.class_section_id', 'class_sections.class_section_name')
|
|
||||||
->get()
|
|
||||||
->toArray();
|
|
||||||
|
|
||||||
$className = $studentsData[0]['class_section_name'] ?? 'Class Name Not Available';
|
|
||||||
|
|
||||||
if (empty($teacherData) || empty($studentsData)) {
|
|
||||||
return redirect()->to('/teacher/classes')->with('error', 'No data found for this class.');
|
|
||||||
}
|
|
||||||
$teacherFirst = $teacherData['teacher_first'] ?? $teacherData['firstname'] ?? '';
|
|
||||||
$teacherLast = $teacherData['teacher_last'] ?? $teacherData['lastname'] ?? '';
|
|
||||||
|
|
||||||
return view('teacher.classes', [
|
|
||||||
'teacher_name' => trim($teacherFirst . ' ' . $teacherLast),
|
|
||||||
'students' => $studentsData,
|
|
||||||
'class_name' => $className,
|
|
||||||
'semester' => $this->semester,
|
|
||||||
'class_section_id' => $classSectionId,
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,545 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Http\Controllers\View;
|
|
||||||
|
|
||||||
use App\Http\Controllers\Controller;
|
|
||||||
use App\Models\ClassPrepAdjustment;
|
|
||||||
use App\Models\ClassPreparationLog;
|
|
||||||
use App\Models\ClassSection;
|
|
||||||
use App\Models\Configuration;
|
|
||||||
use App\Models\StudentClass;
|
|
||||||
use Illuminate\Http\JsonResponse;
|
|
||||||
use Illuminate\Http\RedirectResponse;
|
|
||||||
use Illuminate\Http\Request;
|
|
||||||
use Illuminate\Support\Facades\DB;
|
|
||||||
use Illuminate\View\View;
|
|
||||||
|
|
||||||
class ClassPreparationController extends Controller
|
|
||||||
{
|
|
||||||
protected StudentClass $studentClass;
|
|
||||||
protected ClassPreparationLog $prepLog;
|
|
||||||
protected ClassSection $classSection;
|
|
||||||
protected Configuration $config;
|
|
||||||
protected ClassPrepAdjustment $adjustment;
|
|
||||||
protected ?string $schoolYear;
|
|
||||||
protected ?string $semester;
|
|
||||||
|
|
||||||
private array $allowedPrepCategories = [
|
|
||||||
'Grade Box',
|
|
||||||
'Large Table',
|
|
||||||
'Regular Chair',
|
|
||||||
'Small Chair',
|
|
||||||
'Small Table',
|
|
||||||
'Teacher Chair',
|
|
||||||
'Trash Bin',
|
|
||||||
'White Board',
|
|
||||||
];
|
|
||||||
|
|
||||||
public function __construct(
|
|
||||||
StudentClass $studentClass,
|
|
||||||
ClassPreparationLog $prepLog,
|
|
||||||
ClassSection $classSection,
|
|
||||||
Configuration $config,
|
|
||||||
ClassPrepAdjustment $adjustment
|
|
||||||
) {
|
|
||||||
$this->studentClass = $studentClass;
|
|
||||||
$this->prepLog = $prepLog;
|
|
||||||
$this->classSection = $classSection;
|
|
||||||
$this->config = $config;
|
|
||||||
$this->adjustment = $adjustment;
|
|
||||||
|
|
||||||
$this->schoolYear = $this->config->getConfig('school_year');
|
|
||||||
$this->semester = $this->config->getConfig('semester');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function index(Request $request): View
|
|
||||||
{
|
|
||||||
$schoolYear = (string) ($request->query('school_year') ?? $this->schoolYear ?? '');
|
|
||||||
$semParam = $request->query('semester');
|
|
||||||
$semester = is_string($semParam) && $semParam !== '' ? $semParam : (string) ($this->semester ?? '');
|
|
||||||
$allowed = $this->allowedPrepCategories;
|
|
||||||
|
|
||||||
$classSections = $this->studentClass->newQuery()
|
|
||||||
->selectRaw('class_section_id, COUNT(DISTINCT student_id) AS student_count')
|
|
||||||
->where('school_year', $schoolYear)
|
|
||||||
->where('semester', $semester)
|
|
||||||
->groupBy('class_section_id')
|
|
||||||
->get()
|
|
||||||
->map(fn ($row) => (array) $row)
|
|
||||||
->toArray();
|
|
||||||
|
|
||||||
$inventoryMap = $this->buildInventoryMap($schoolYear, $semester);
|
|
||||||
|
|
||||||
$requiredTotals = array_fill_keys($allowed, 0);
|
|
||||||
$prepResults = [];
|
|
||||||
|
|
||||||
foreach ($classSections as $section) {
|
|
||||||
$classSectionId = (string) ($section['class_section_id'] ?? '');
|
|
||||||
$studentCount = (int) ($section['student_count'] ?? 0);
|
|
||||||
$classLevel = $this->getClassLevelBySection($classSectionId);
|
|
||||||
$className = $this->classSection->getClassSectionNameBySectionId($classSectionId) ?? $classSectionId;
|
|
||||||
|
|
||||||
$baseItems = $this->calculatePrepItems($studentCount, $classLevel, $classSectionId);
|
|
||||||
|
|
||||||
$rawAdjustments = $this->adjustment->newQuery()
|
|
||||||
->where('class_section_id', $classSectionId)
|
|
||||||
->where('school_year', $schoolYear)
|
|
||||||
->where('adjustable', 1)
|
|
||||||
->get()
|
|
||||||
->map(fn ($row) => (array) $row)
|
|
||||||
->toArray();
|
|
||||||
|
|
||||||
$adjMap = ['Large Table' => 0, 'Small Table' => 0];
|
|
||||||
|
|
||||||
foreach ($rawAdjustments as $adjustment) {
|
|
||||||
$item = $adjustment['item_name'] ?? '';
|
|
||||||
$delta = (int) ($adjustment['adjustment'] ?? 0);
|
|
||||||
|
|
||||||
if (array_key_exists($item, $adjMap)) {
|
|
||||||
$adjMap[$item] = $delta;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($baseItems[$item])) {
|
|
||||||
$baseItems[$item] = max(0, (int) $baseItems[$item] + $delta);
|
|
||||||
} elseif (in_array($item, $allowed, true)) {
|
|
||||||
$baseItems[$item] = max(0, $delta);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($allowed as $category) {
|
|
||||||
$requiredTotals[$category] += (int) ($baseItems[$category] ?? 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
$oldSnap = $this->prepLog->newQuery()
|
|
||||||
->where('class_section_id', $classSectionId)
|
|
||||||
->where('school_year', $schoolYear)
|
|
||||||
->orderBy('created_at', 'DESC')
|
|
||||||
->first();
|
|
||||||
|
|
||||||
$oldPrep = $oldSnap ? json_decode($oldSnap['prep_data'] ?? '[]', true) : [];
|
|
||||||
$hasChanged = $this->hasPrepChanged($baseItems, $oldPrep);
|
|
||||||
|
|
||||||
$prepResults[] = [
|
|
||||||
'class_section' => $className,
|
|
||||||
'class_section_id' => $classSectionId,
|
|
||||||
'student_count' => $studentCount,
|
|
||||||
'class_level' => $classLevel,
|
|
||||||
'prep_items' => $baseItems,
|
|
||||||
'needs_print' => $hasChanged,
|
|
||||||
'last_printed_at' => $oldSnap['created_at'] ?? null,
|
|
||||||
'adjustments' => $adjMap,
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
$shortages = [];
|
|
||||||
foreach ($requiredTotals as $item => $required) {
|
|
||||||
$available = (int) ($inventoryMap[$item] ?? 0);
|
|
||||||
if ($available < (int) $required) {
|
|
||||||
$shortages[$item] = (int) $required - $available;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return view('class_prep/list', [
|
|
||||||
'prepResults' => $prepResults,
|
|
||||||
'schoolYear' => $schoolYear,
|
|
||||||
'semester' => $semester,
|
|
||||||
'shortages' => $shortages,
|
|
||||||
'totalNeeded' => $requiredTotals,
|
|
||||||
'available' => $inventoryMap,
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function saveAdjustment(Request $request): RedirectResponse
|
|
||||||
{
|
|
||||||
$data = $request->all();
|
|
||||||
$sectionId = (string) ($data['class_section_id'] ?? '');
|
|
||||||
$schoolYear = (string) ($data['school_year'] ?? $this->schoolYear ?? '');
|
|
||||||
$adjustments = is_array($data['adjustments'] ?? null) ? $data['adjustments'] : [];
|
|
||||||
|
|
||||||
foreach ($adjustments as $itemName => $adjustment) {
|
|
||||||
$row = $this->adjustment->newQuery()
|
|
||||||
->where('class_section_id', $sectionId)
|
|
||||||
->where('school_year', $schoolYear)
|
|
||||||
->where('item_name', $itemName)
|
|
||||||
->first();
|
|
||||||
|
|
||||||
if ($row) {
|
|
||||||
$this->adjustment->update($row['id'], [
|
|
||||||
'adjustment' => (int) $adjustment,
|
|
||||||
'adjustable' => 1,
|
|
||||||
]);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->adjustment->insert([
|
|
||||||
'class_section_id' => $sectionId,
|
|
||||||
'item_name' => $itemName,
|
|
||||||
'adjustment' => (int) $adjustment,
|
|
||||||
'school_year' => $schoolYear,
|
|
||||||
'adjustable' => 1,
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return redirect()->to('/class-prep?school_year=' . urlencode($schoolYear))
|
|
||||||
->with('success', 'Adjustments saved successfully.');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function print(string $classSectionId, string $schoolYear): View
|
|
||||||
{
|
|
||||||
$className = $this->classSection->getClassSectionNameBySectionId($classSectionId) ?? $classSectionId;
|
|
||||||
|
|
||||||
$studentRow = $this->studentClass->newQuery()
|
|
||||||
->selectRaw('COUNT(DISTINCT student_id) AS cnt')
|
|
||||||
->where('class_section_id', $classSectionId)
|
|
||||||
->where('school_year', $schoolYear)
|
|
||||||
->where('semester', $this->semester)
|
|
||||||
->first();
|
|
||||||
|
|
||||||
$studentCount = (int) ($studentRow['cnt'] ?? 0);
|
|
||||||
$classLevel = $this->getClassLevelBySection($classSectionId);
|
|
||||||
$items = $this->calculatePrepItems($studentCount, $classLevel, $classSectionId);
|
|
||||||
|
|
||||||
$rawAdjustments = $this->adjustment->newQuery()
|
|
||||||
->where('class_section_id', $classSectionId)
|
|
||||||
->where('school_year', $schoolYear)
|
|
||||||
->where('adjustable', 1)
|
|
||||||
->get()
|
|
||||||
->map(fn ($row) => (array) $row)
|
|
||||||
->toArray();
|
|
||||||
|
|
||||||
foreach ($rawAdjustments as $adjustment) {
|
|
||||||
$item = $adjustment['item_name'] ?? '';
|
|
||||||
$delta = (int) ($adjustment['adjustment'] ?? 0);
|
|
||||||
if (isset($items[$item])) {
|
|
||||||
$items[$item] = max(0, (int) $items[$item] + $delta);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->prepLog->insert([
|
|
||||||
'class_section_id' => $classSectionId,
|
|
||||||
'class_section' => $className,
|
|
||||||
'school_year' => $schoolYear,
|
|
||||||
'prep_data' => json_encode($items),
|
|
||||||
'created_at' => utc_now(),
|
|
||||||
]);
|
|
||||||
|
|
||||||
return view('class_prep/print', [
|
|
||||||
'classSectionId' => $classSectionId,
|
|
||||||
'classSection' => $className,
|
|
||||||
'schoolYear' => $schoolYear,
|
|
||||||
'prepItems' => $items,
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function apiList(Request $request): JsonResponse
|
|
||||||
{
|
|
||||||
$schoolYear = (string) ($request->query('school_year') ?? $this->schoolYear ?? '');
|
|
||||||
$allowed = $this->allowedPrepCategories;
|
|
||||||
|
|
||||||
$classSections = $this->studentClass->newQuery()
|
|
||||||
->selectRaw('class_section_id, COUNT(DISTINCT student_id) AS student_count')
|
|
||||||
->where('school_year', $schoolYear)
|
|
||||||
->where('semester', $this->semester)
|
|
||||||
->groupBy('class_section_id')
|
|
||||||
->get()
|
|
||||||
->map(fn ($row) => (array) $row)
|
|
||||||
->toArray();
|
|
||||||
|
|
||||||
$inventoryMap = $this->buildInventoryMap($schoolYear, $this->semester);
|
|
||||||
|
|
||||||
$requiredTotals = array_fill_keys($allowed, 0);
|
|
||||||
$results = [];
|
|
||||||
|
|
||||||
foreach ($classSections as $row) {
|
|
||||||
$classSectionId = (string) ($row['class_section_id'] ?? '');
|
|
||||||
$studentCount = (int) ($row['student_count'] ?? 0);
|
|
||||||
$classLevel = $this->getClassLevelBySection($classSectionId);
|
|
||||||
$className = $this->classSection->getClassSectionNameBySectionId($classSectionId) ?? $classSectionId;
|
|
||||||
|
|
||||||
$baseItems = $this->calculatePrepItems($studentCount, $classLevel, $classSectionId);
|
|
||||||
|
|
||||||
$rawAdjustments = $this->adjustment->newQuery()
|
|
||||||
->where('class_section_id', $classSectionId)
|
|
||||||
->where('school_year', $schoolYear)
|
|
||||||
->where('adjustable', 1)
|
|
||||||
->get()
|
|
||||||
->map(fn ($row) => (array) $row)
|
|
||||||
->toArray();
|
|
||||||
|
|
||||||
$adjMap = ['Large Table' => 0, 'Small Table' => 0];
|
|
||||||
|
|
||||||
foreach ($rawAdjustments as $adjustment) {
|
|
||||||
$item = $adjustment['item_name'] ?? '';
|
|
||||||
$delta = (int) ($adjustment['adjustment'] ?? 0);
|
|
||||||
if (array_key_exists($item, $adjMap)) {
|
|
||||||
$adjMap[$item] = $delta;
|
|
||||||
}
|
|
||||||
if (isset($baseItems[$item])) {
|
|
||||||
$baseItems[$item] = max(0, (int) $baseItems[$item] + $delta);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($allowed as $cat) {
|
|
||||||
$requiredTotals[$cat] += (int) ($baseItems[$cat] ?? 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
$oldSnap = $this->prepLog->newQuery()
|
|
||||||
->where('class_section_id', $classSectionId)
|
|
||||||
->where('school_year', $schoolYear)
|
|
||||||
->orderBy('created_at', 'DESC')
|
|
||||||
->first();
|
|
||||||
|
|
||||||
$oldPrep = $oldSnap ? json_decode($oldSnap['prep_data'] ?? '[]', true) : [];
|
|
||||||
$hasChanged = $this->hasPrepChanged($baseItems, $oldPrep);
|
|
||||||
|
|
||||||
$results[] = [
|
|
||||||
'class_section' => $className,
|
|
||||||
'class_section_id' => $classSectionId,
|
|
||||||
'student_count' => $studentCount,
|
|
||||||
'class_level' => $classLevel,
|
|
||||||
'prep_items' => $baseItems,
|
|
||||||
'needs_print' => $hasChanged,
|
|
||||||
'last_printed_at' => $oldSnap['created_at'] ?? null,
|
|
||||||
'adjustments' => $adjMap,
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
$shortages = [];
|
|
||||||
foreach ($requiredTotals as $item => $required) {
|
|
||||||
$available = (int) ($inventoryMap[$item] ?? 0);
|
|
||||||
if ($available < (int) $required) {
|
|
||||||
$shortages[$item] = (int) $required - $available;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return response()->json([
|
|
||||||
'ok' => true,
|
|
||||||
'schoolYear' => $schoolYear,
|
|
||||||
'results' => $results,
|
|
||||||
'totals' => $requiredTotals,
|
|
||||||
'shortages' => $shortages,
|
|
||||||
'csrf_token' => csrf_token(),
|
|
||||||
'csrf_hash' => csrf_token(),
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function apiMarkPrinted(Request $request): JsonResponse
|
|
||||||
{
|
|
||||||
$schoolYear = (string) ($request->post('school_year') ?? $this->schoolYear ?? '');
|
|
||||||
$ids = $request->post('class_section_ids', []);
|
|
||||||
if (!is_array($ids)) {
|
|
||||||
$ids = $ids ? [$ids] : [];
|
|
||||||
}
|
|
||||||
$ids = array_values(array_unique(array_filter(array_map('strval', $ids))));
|
|
||||||
|
|
||||||
$count = 0;
|
|
||||||
foreach ($ids as $classSectionId) {
|
|
||||||
$studentRow = $this->studentClass->newQuery()
|
|
||||||
->selectRaw('COUNT(DISTINCT student_id) AS cnt')
|
|
||||||
->where('class_section_id', $classSectionId)
|
|
||||||
->where('school_year', $schoolYear)
|
|
||||||
->where('semester', $this->semester)
|
|
||||||
->first();
|
|
||||||
|
|
||||||
$studentCount = (int) ($studentRow['cnt'] ?? 0);
|
|
||||||
$classLevel = $this->getClassLevelBySection($classSectionId);
|
|
||||||
$className = $this->classSection->getClassSectionNameBySectionId($classSectionId) ?? $classSectionId;
|
|
||||||
$items = $this->calculatePrepItems($studentCount, $classLevel, $classSectionId);
|
|
||||||
|
|
||||||
$rawAdjustments = $this->adjustment->newQuery()
|
|
||||||
->where('class_section_id', $classSectionId)
|
|
||||||
->where('school_year', $schoolYear)
|
|
||||||
->where('adjustable', 1)
|
|
||||||
->get()
|
|
||||||
->map(fn ($row) => (array) $row)
|
|
||||||
->toArray();
|
|
||||||
|
|
||||||
foreach ($rawAdjustments as $adjustment) {
|
|
||||||
$item = $adjustment['item_name'] ?? '';
|
|
||||||
$delta = (int) ($adjustment['adjustment'] ?? 0);
|
|
||||||
if (isset($items[$item])) {
|
|
||||||
$items[$item] = max(0, (int) $items[$item] + $delta);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
$this->prepLog->insert([
|
|
||||||
'class_section_id' => $classSectionId,
|
|
||||||
'class_section' => $className,
|
|
||||||
'school_year' => $schoolYear,
|
|
||||||
'prep_data' => json_encode($items),
|
|
||||||
'created_at' => utc_now(),
|
|
||||||
]);
|
|
||||||
$count++;
|
|
||||||
} catch (\Throwable $e) {
|
|
||||||
// ignore and continue to next section
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return response()->json([
|
|
||||||
'ok' => true,
|
|
||||||
'updated' => $count,
|
|
||||||
'csrf_token' => csrf_token(),
|
|
||||||
'csrf_hash' => csrf_token(),
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
private function getTeacherCountForSection(string $classSectionId, ?string $schoolYear = null): int
|
|
||||||
{
|
|
||||||
$schoolYear = $schoolYear ?? $this->schoolYear;
|
|
||||||
|
|
||||||
$row = DB::table('teacher_class')
|
|
||||||
->selectRaw('COUNT(*) AS cnt')
|
|
||||||
->where('class_section_id', $classSectionId)
|
|
||||||
->whereIn('position', ['main', 'ta'])
|
|
||||||
->where('school_year', $schoolYear)
|
|
||||||
->first();
|
|
||||||
|
|
||||||
return (int) ($row->cnt ?? 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
private function calculatePrepItems(int $students, int $classLevel, string $classSectionId): array
|
|
||||||
{
|
|
||||||
$allowed = $this->allowedPrepCategories;
|
|
||||||
$items = array_fill_keys($allowed, 0);
|
|
||||||
|
|
||||||
$categories = DB::table('inventory_categories')
|
|
||||||
->select('name', 'grade_min', 'grade_max')
|
|
||||||
->where('type', 'classroom')
|
|
||||||
->whereIn('name', $allowed)
|
|
||||||
->orderBy('name')
|
|
||||||
->get()
|
|
||||||
->map(fn ($row) => (array) $row)
|
|
||||||
->toArray();
|
|
||||||
|
|
||||||
$isLowerGrades = in_array($classLevel, [1, 2], true);
|
|
||||||
$teacherCount = $this->getTeacherCountForSection($classSectionId);
|
|
||||||
|
|
||||||
foreach ($categories as $category) {
|
|
||||||
$name = $category['name'] ?? '';
|
|
||||||
$gradeMin = $category['grade_min'];
|
|
||||||
$gradeMax = $category['grade_max'];
|
|
||||||
|
|
||||||
if ($gradeMin !== null && $classLevel < (int) $gradeMin) {
|
|
||||||
$items[$name] = 0;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if ($gradeMax !== null && $classLevel > (int) $gradeMax) {
|
|
||||||
$items[$name] = 0;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
$qty = 0;
|
|
||||||
switch (strtolower($name)) {
|
|
||||||
case 'small table':
|
|
||||||
$qty = $isLowerGrades ? (int) ceil($students / 3) : 0;
|
|
||||||
break;
|
|
||||||
case 'large table':
|
|
||||||
$qty = $isLowerGrades ? 0 : (int) ceil($students / 4);
|
|
||||||
break;
|
|
||||||
case 'small chair':
|
|
||||||
$qty = $isLowerGrades ? $students : 0;
|
|
||||||
break;
|
|
||||||
case 'regular chair':
|
|
||||||
$qty = $isLowerGrades ? 0 : $students;
|
|
||||||
break;
|
|
||||||
case 'teacher chair':
|
|
||||||
$qty = $teacherCount;
|
|
||||||
break;
|
|
||||||
case 'trash bin':
|
|
||||||
case 'white board':
|
|
||||||
case 'grade box':
|
|
||||||
$qty = 1;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
$qty = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (array_key_exists($name, $items)) {
|
|
||||||
$items[$name] = $qty;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $items;
|
|
||||||
}
|
|
||||||
|
|
||||||
private function hasPrepChanged(array $new, array $old): bool
|
|
||||||
{
|
|
||||||
ksort($new);
|
|
||||||
ksort($old);
|
|
||||||
|
|
||||||
return json_encode($new) !== json_encode($old);
|
|
||||||
}
|
|
||||||
|
|
||||||
private function buildInventoryMap(string $schoolYear, string $semester): array
|
|
||||||
{
|
|
||||||
$allowed = $this->allowedPrepCategories;
|
|
||||||
$inventoryMap = array_fill_keys($allowed, 0);
|
|
||||||
|
|
||||||
$queries = [
|
|
||||||
DB::table('inventory_items as ii')
|
|
||||||
->selectRaw('ic.name AS item_name, COALESCE(SUM(ii.good_qty),0) AS available')
|
|
||||||
->join('inventory_categories as ic', 'ic.id', '=', 'ii.category_id')
|
|
||||||
->where('ii.type', 'classroom')
|
|
||||||
->where('ii.school_year', $schoolYear)
|
|
||||||
->where('ii.semester', $semester)
|
|
||||||
->whereIn('ic.name', $allowed)
|
|
||||||
->groupBy('ic.name'),
|
|
||||||
DB::table('inventory_items')
|
|
||||||
->selectRaw('name AS item_name, COALESCE(SUM(good_qty),0) AS available')
|
|
||||||
->where('type', 'classroom')
|
|
||||||
->where('school_year', $schoolYear)
|
|
||||||
->where('semester', $semester)
|
|
||||||
->whereIn('name', $allowed)
|
|
||||||
->groupBy('name'),
|
|
||||||
DB::table('inventory_items as ii')
|
|
||||||
->selectRaw('ic.name AS item_name, COALESCE(SUM(CASE WHEN ii.`condition`="good" THEN ii.quantity ELSE 0 END),0) AS available')
|
|
||||||
->join('inventory_categories as ic', 'ic.id', '=', 'ii.category_id')
|
|
||||||
->where('ii.type', 'classroom')
|
|
||||||
->where('ii.school_year', $schoolYear)
|
|
||||||
->where('ii.semester', $semester)
|
|
||||||
->whereIn('ic.name', $allowed)
|
|
||||||
->groupBy('ic.name'),
|
|
||||||
DB::table('inventory_items')
|
|
||||||
->selectRaw('name AS item_name, COALESCE(SUM(CASE WHEN `condition`="good" THEN quantity ELSE 0 END),0) AS available')
|
|
||||||
->where('type', 'classroom')
|
|
||||||
->where('school_year', $schoolYear)
|
|
||||||
->where('semester', $semester)
|
|
||||||
->whereIn('name', $allowed)
|
|
||||||
->groupBy('name'),
|
|
||||||
];
|
|
||||||
|
|
||||||
foreach ($queries as $query) {
|
|
||||||
foreach ($query->get()->toArray() as $row) {
|
|
||||||
$row = (array) $row;
|
|
||||||
$name = (string) ($row['item_name'] ?? $row['name'] ?? '');
|
|
||||||
$val = (int) ($row['available'] ?? 0);
|
|
||||||
|
|
||||||
if ($name !== '' && isset($inventoryMap[$name])) {
|
|
||||||
$inventoryMap[$name] = max($inventoryMap[$name], $val);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $inventoryMap;
|
|
||||||
}
|
|
||||||
|
|
||||||
private function getClassLevelBySection(string $classSectionId): int
|
|
||||||
{
|
|
||||||
if (preg_match('/^(kg|k)(\b|[^a-z0-9])/i', $classSectionId)) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
$numeric = (int) preg_replace('/\D/', '', $classSectionId);
|
|
||||||
if ($numeric > 0 && $numeric < 30) {
|
|
||||||
$firstDigit = (int) substr((string) $numeric, 0, 1);
|
|
||||||
return match ($firstDigit) {
|
|
||||||
1 => 1,
|
|
||||||
2 => 2,
|
|
||||||
default => 3,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return 3;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Http\Controllers\View;
|
|
||||||
|
|
||||||
use App\Http\Controllers\Controller;
|
|
||||||
use App\Models\Role;
|
|
||||||
use Illuminate\Http\RedirectResponse;
|
|
||||||
|
|
||||||
class DashboardRedirectController extends Controller
|
|
||||||
{
|
|
||||||
public function __construct(protected Role $role)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public function dashboard(): RedirectResponse
|
|
||||||
{
|
|
||||||
$session = session();
|
|
||||||
$roles = $session->get('roles') ?? [];
|
|
||||||
|
|
||||||
if (empty($roles) && $session->has('role')) {
|
|
||||||
$roles = [$session->get('role')];
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->redirectToDashboard($roles);
|
|
||||||
}
|
|
||||||
|
|
||||||
private function redirectToDashboard(array $roles): RedirectResponse
|
|
||||||
{
|
|
||||||
if (empty($roles)) {
|
|
||||||
log_message('error', 'Empty roles array passed to redirectToDashboard.');
|
|
||||||
return redirect()->to('/landing_page/guest_dashboard');
|
|
||||||
}
|
|
||||||
|
|
||||||
$rows = $this->role->findByNamesOrSlugs($roles);
|
|
||||||
|
|
||||||
if (!empty($rows)) {
|
|
||||||
$route = $rows[0]['dashboard_route'] ?? '/landing_page/guest_dashboard';
|
|
||||||
log_message('debug', 'Redirecting user to: ' . $route);
|
|
||||||
return redirect()->to($route);
|
|
||||||
}
|
|
||||||
|
|
||||||
log_message('warning', 'No matching role found. Redirecting to guest dashboard.');
|
|
||||||
return redirect()->to('/landing_page/guest_dashboard');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -35,8 +35,6 @@ class Kernel extends HttpKernel
|
|||||||
'web' => [
|
'web' => [
|
||||||
\App\Http\Middleware\EncryptCookies::class,
|
\App\Http\Middleware\EncryptCookies::class,
|
||||||
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
|
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
|
||||||
\Illuminate\Session\Middleware\StartSession::class,
|
|
||||||
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
|
|
||||||
\Illuminate\Routing\Middleware\SubstituteBindings::class,
|
\Illuminate\Routing\Middleware\SubstituteBindings::class,
|
||||||
],
|
],
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,65 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Middleware;
|
||||||
|
|
||||||
|
use Closure;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
|
use PHPOpenSourceSaver\JWTAuth\Exceptions\JWTException;
|
||||||
|
use PHPOpenSourceSaver\JWTAuth\Facades\JWTAuth;
|
||||||
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
|
|
||||||
|
class ApiDocsAuth
|
||||||
|
{
|
||||||
|
public function handle(Request $request, Closure $next): Response
|
||||||
|
{
|
||||||
|
$user = Auth::user();
|
||||||
|
if (!$user) {
|
||||||
|
$authHeader = (string) $request->header('Authorization');
|
||||||
|
if ($authHeader !== '' && stripos($authHeader, 'Bearer ') === 0) {
|
||||||
|
$token = trim(substr($authHeader, 7));
|
||||||
|
if ($token === '') {
|
||||||
|
return $this->deny('Missing token.', 401);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
$user = JWTAuth::setToken($token)->authenticate();
|
||||||
|
if ($user) {
|
||||||
|
Auth::setUser($user);
|
||||||
|
}
|
||||||
|
} catch (JWTException $e) {
|
||||||
|
$user = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$user) {
|
||||||
|
return $this->deny('Unauthorized access to documentation.', 401);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$this->userIsAdmin((int) $user->id)) {
|
||||||
|
return $this->deny('Admin privileges required.', 403);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $next($request);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function userIsAdmin(int $userId): bool
|
||||||
|
{
|
||||||
|
return DB::table('user_roles as ur')
|
||||||
|
->join('roles as r', 'r.id', '=', 'ur.role_id')
|
||||||
|
->where('ur.user_id', $userId)
|
||||||
|
->whereNull('ur.deleted_at')
|
||||||
|
->whereRaw('LOWER(r.name) = ?', ['admin'])
|
||||||
|
->exists();
|
||||||
|
}
|
||||||
|
|
||||||
|
private function deny(string $message, int $status): Response
|
||||||
|
{
|
||||||
|
return response()->json([
|
||||||
|
'status' => false,
|
||||||
|
'message' => $message,
|
||||||
|
], $status);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Middleware;
|
||||||
|
|
||||||
|
use Closure;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
use PHPOpenSourceSaver\JWTAuth\Exceptions\JWTException;
|
||||||
|
use PHPOpenSourceSaver\JWTAuth\Facades\JWTAuth;
|
||||||
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
|
|
||||||
|
class ApiJwtAuth
|
||||||
|
{
|
||||||
|
public function handle(Request $request, Closure $next): Response
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$user = JWTAuth::parseToken()->authenticate();
|
||||||
|
if (!$user) {
|
||||||
|
return response()->json(['status' => false, 'message' => 'Unauthorized.'], 401);
|
||||||
|
}
|
||||||
|
|
||||||
|
Auth::setUser($user);
|
||||||
|
} catch (JWTException $e) {
|
||||||
|
return response()->json(['status' => false, 'message' => 'Unauthorized.'], 401);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $next($request);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Middleware;
|
||||||
|
|
||||||
|
use App\Services\System\CleanupSchedulerService;
|
||||||
|
use Closure;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
|
|
||||||
|
class CleanupScheduler
|
||||||
|
{
|
||||||
|
public function __construct(private CleanupSchedulerService $service)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public function handle(Request $request, Closure $next): Response
|
||||||
|
{
|
||||||
|
$cacheKey = 'last_cleanup_run';
|
||||||
|
if ($this->service->shouldRun($cacheKey, 2)) {
|
||||||
|
$this->service->runUnverifiedCleanup();
|
||||||
|
$this->service->markRun($cacheKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $next($request);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Middleware;
|
||||||
|
|
||||||
|
use App\Services\System\TimeService;
|
||||||
|
use Closure;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
|
|
||||||
|
class PrimeTimezone
|
||||||
|
{
|
||||||
|
public function __construct(private TimeService $timeService)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public function handle(Request $request, Closure $next): Response
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$this->timeService->primeFromRequest($request);
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
// ignore; fallback detection still works
|
||||||
|
}
|
||||||
|
|
||||||
|
return $next($request);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Middleware;
|
||||||
|
|
||||||
|
use App\Services\Auth\PermissionCheckService;
|
||||||
|
use Closure;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
|
|
||||||
|
class RequirePermission
|
||||||
|
{
|
||||||
|
public function __construct(private PermissionCheckService $permissions)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public function handle(Request $request, Closure $next, string $permission): Response
|
||||||
|
{
|
||||||
|
$userId = (int) ($request->user()?->id ?? 0);
|
||||||
|
if ($userId <= 0) {
|
||||||
|
return response()->json(['status' => false, 'message' => 'Unauthorized.'], 401);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$this->permissions->hasPermission($userId, $permission)) {
|
||||||
|
if ($request->expectsJson()) {
|
||||||
|
return response()->json(['status' => false, 'message' => 'Access denied.'], 403);
|
||||||
|
}
|
||||||
|
return response()->json(['status' => false, 'message' => 'Access denied.'], 403);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $next($request);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests\Attendance;
|
||||||
|
|
||||||
|
use App\Http\Requests\ApiFormRequest;
|
||||||
|
|
||||||
|
class LateSlipLogIndexRequest extends ApiFormRequest
|
||||||
|
{
|
||||||
|
public function authorize(): bool
|
||||||
|
{
|
||||||
|
return $this->user() !== null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'school_year' => ['nullable', 'string', 'max:9'],
|
||||||
|
'semester' => ['nullable', 'string', 'max:255'],
|
||||||
|
'q' => ['nullable', 'string', 'max:120'],
|
||||||
|
'date_from' => ['nullable', 'date'],
|
||||||
|
'date_to' => ['nullable', 'date'],
|
||||||
|
'sort_by' => ['nullable', 'string', 'in:id,slip_date,student_name,printed_at,updated_at'],
|
||||||
|
'sort_dir' => ['nullable', 'string', 'in:asc,desc'],
|
||||||
|
'page' => ['nullable', 'integer', 'min:1'],
|
||||||
|
'per_page' => ['nullable', 'integer', 'min:1', 'max:200'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Http\Requests\Auth;
|
|
||||||
|
|
||||||
use App\Http\Requests\ApiFormRequest;
|
|
||||||
|
|
||||||
class SessionTimeoutCheckRequest extends ApiFormRequest
|
|
||||||
{
|
|
||||||
public function authorize(): bool
|
|
||||||
{
|
|
||||||
return auth()->check();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function rules(): array
|
|
||||||
{
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Http\Requests\Auth;
|
|
||||||
|
|
||||||
use App\Http\Requests\ApiFormRequest;
|
|
||||||
|
|
||||||
class SessionTimeoutConfigRequest extends ApiFormRequest
|
|
||||||
{
|
|
||||||
public function authorize(): bool
|
|
||||||
{
|
|
||||||
return auth()->check();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function rules(): array
|
|
||||||
{
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Http\Requests\Auth;
|
|
||||||
|
|
||||||
use App\Http\Requests\ApiFormRequest;
|
|
||||||
|
|
||||||
class SessionTimeoutPingRequest extends ApiFormRequest
|
|
||||||
{
|
|
||||||
public function authorize(): bool
|
|
||||||
{
|
|
||||||
return auth()->check();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function rules(): array
|
|
||||||
{
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests\ClassPreparation;
|
||||||
|
|
||||||
|
use App\Http\Requests\ApiFormRequest;
|
||||||
|
|
||||||
|
class ClassPreparationAdjustmentRequest extends ApiFormRequest
|
||||||
|
{
|
||||||
|
public function authorize(): bool
|
||||||
|
{
|
||||||
|
return $this->user() !== null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'class_section_id' => ['required', 'string', 'max:32'],
|
||||||
|
'school_year' => ['nullable', 'string', 'max:9'],
|
||||||
|
'adjustments' => ['required', 'array'],
|
||||||
|
'adjustments.*' => ['required', 'integer'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests\ClassPreparation;
|
||||||
|
|
||||||
|
use App\Http\Requests\ApiFormRequest;
|
||||||
|
|
||||||
|
class ClassPreparationIndexRequest extends ApiFormRequest
|
||||||
|
{
|
||||||
|
public function authorize(): bool
|
||||||
|
{
|
||||||
|
return $this->user() !== null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'school_year' => ['nullable', 'string', 'max:9'],
|
||||||
|
'semester' => ['nullable', 'string', 'max:255'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests\ClassPreparation;
|
||||||
|
|
||||||
|
use App\Http\Requests\ApiFormRequest;
|
||||||
|
|
||||||
|
class ClassPreparationMarkPrintedRequest extends ApiFormRequest
|
||||||
|
{
|
||||||
|
public function authorize(): bool
|
||||||
|
{
|
||||||
|
return $this->user() !== null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'school_year' => ['required', 'string', 'max:9'],
|
||||||
|
'semester' => ['nullable', 'string', 'max:255'],
|
||||||
|
'class_section_ids' => ['required', 'array'],
|
||||||
|
'class_section_ids.*' => ['required', 'string', 'max:32'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests\ClassPreparation;
|
||||||
|
|
||||||
|
use App\Http\Requests\ApiFormRequest;
|
||||||
|
|
||||||
|
class ClassPreparationPrintRequest extends ApiFormRequest
|
||||||
|
{
|
||||||
|
public function authorize(): bool
|
||||||
|
{
|
||||||
|
return $this->user() !== null;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function prepareForValidation(): void
|
||||||
|
{
|
||||||
|
parent::prepareForValidation();
|
||||||
|
|
||||||
|
$this->merge([
|
||||||
|
'class_section_id' => $this->route('classSectionId'),
|
||||||
|
'school_year' => $this->route('schoolYear'),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'class_section_id' => ['required', 'string', 'max:32'],
|
||||||
|
'school_year' => ['required', 'string', 'max:9'],
|
||||||
|
'semester' => ['nullable', 'string', 'max:255'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests\Classes;
|
||||||
|
|
||||||
|
use App\Http\Requests\ApiFormRequest;
|
||||||
|
|
||||||
|
class ClassSectionIndexRequest extends ApiFormRequest
|
||||||
|
{
|
||||||
|
public function authorize(): bool
|
||||||
|
{
|
||||||
|
return $this->user() !== null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'search' => ['nullable', 'string', 'max:120'],
|
||||||
|
'class_id' => ['nullable', 'integer', 'min:1'],
|
||||||
|
'school_year' => ['nullable', 'string', 'max:9'],
|
||||||
|
'semester' => ['nullable', 'string', 'max:255'],
|
||||||
|
'sort_by' => ['nullable', 'string', 'in:class_section_name,class_section_id,class_id,school_year,semester,class_name'],
|
||||||
|
'sort_dir' => ['nullable', 'string', 'in:asc,desc'],
|
||||||
|
'page' => ['nullable', 'integer', 'min:1'],
|
||||||
|
'per_page' => ['nullable', 'integer', 'min:1', 'max:200'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests\Classes;
|
||||||
|
|
||||||
|
use App\Http\Requests\ApiFormRequest;
|
||||||
|
use Illuminate\Validation\Rule;
|
||||||
|
|
||||||
|
class ClassSectionStoreRequest extends ApiFormRequest
|
||||||
|
{
|
||||||
|
public function authorize(): bool
|
||||||
|
{
|
||||||
|
return $this->user() !== null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'class_id' => ['required', 'integer', 'min:1'],
|
||||||
|
'class_section_id' => ['required', 'integer', 'min:1', Rule::unique('classSection', 'class_section_id')],
|
||||||
|
'class_section_name' => ['required', 'string', 'max:100'],
|
||||||
|
'semester' => ['required', 'string', 'max:255'],
|
||||||
|
'school_year' => ['required', 'string', 'max:9'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests\Classes;
|
||||||
|
|
||||||
|
use App\Http\Requests\ApiFormRequest;
|
||||||
|
use Illuminate\Validation\Rule;
|
||||||
|
|
||||||
|
class ClassSectionUpdateRequest extends ApiFormRequest
|
||||||
|
{
|
||||||
|
public function authorize(): bool
|
||||||
|
{
|
||||||
|
return $this->user() !== null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
$section = $this->route('classSection');
|
||||||
|
$sectionId = is_object($section) ? $section->id : $section;
|
||||||
|
|
||||||
|
return [
|
||||||
|
'class_id' => ['sometimes', 'integer', 'min:1'],
|
||||||
|
'class_section_id' => [
|
||||||
|
'sometimes',
|
||||||
|
'integer',
|
||||||
|
'min:1',
|
||||||
|
Rule::unique('classSection', 'class_section_id')->ignore($sectionId),
|
||||||
|
],
|
||||||
|
'class_section_name' => ['sometimes', 'string', 'max:100'],
|
||||||
|
'semester' => ['sometimes', 'string', 'max:255'],
|
||||||
|
'school_year' => ['sometimes', 'string', 'max:9'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests\Frontend;
|
||||||
|
|
||||||
|
use App\Http\Requests\ApiFormRequest;
|
||||||
|
|
||||||
|
class ContactSubmitRequest extends ApiFormRequest
|
||||||
|
{
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'email' => ['required', 'email', 'max:255'],
|
||||||
|
'message' => ['required', 'string', 'min:10'],
|
||||||
|
'subject' => ['nullable', 'string', 'max:255'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests\Frontend;
|
||||||
|
|
||||||
|
use App\Http\Requests\ApiFormRequest;
|
||||||
|
|
||||||
|
class LandingTeacherRequest extends ApiFormRequest
|
||||||
|
{
|
||||||
|
public function authorize(): bool
|
||||||
|
{
|
||||||
|
return $this->user() !== null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'class_section_id' => ['nullable', 'integer', 'min:1'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests\Messaging;
|
||||||
|
|
||||||
|
use App\Http\Requests\ApiFormRequest;
|
||||||
|
|
||||||
|
class MessageIndexRequest extends ApiFormRequest
|
||||||
|
{
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'page' => ['nullable', 'integer', 'min:1'],
|
||||||
|
'per_page' => ['nullable', 'integer', 'min:1', 'max:100'],
|
||||||
|
'priority' => ['nullable', 'in:low,normal,high'],
|
||||||
|
'read_status' => ['nullable', 'in:0,1'],
|
||||||
|
'search' => ['nullable', 'string', 'max:255'],
|
||||||
|
'sort_by' => ['nullable', 'in:sent_datetime,subject,priority'],
|
||||||
|
'sort_dir' => ['nullable', 'in:asc,desc'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests\Messaging;
|
||||||
|
|
||||||
|
use App\Http\Requests\ApiFormRequest;
|
||||||
|
|
||||||
|
class MessageSendRequest extends ApiFormRequest
|
||||||
|
{
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'recipient_id' => ['nullable', 'integer', 'min:1', 'required_without:recipient_role'],
|
||||||
|
'recipient_role' => ['nullable', 'string', 'required_without:recipient_id', 'in:teacher,parent,admin,student,guest,administrator'],
|
||||||
|
'subject' => ['required', 'string', 'max:255'],
|
||||||
|
'message' => ['required', 'string'],
|
||||||
|
'priority' => ['nullable', 'in:low,normal,high'],
|
||||||
|
'status' => ['nullable', 'in:sent,received,draft,trashed'],
|
||||||
|
'semester' => ['nullable', 'string', 'max:255'],
|
||||||
|
'school_year' => ['nullable', 'string', 'max:20'],
|
||||||
|
'attachment' => ['nullable', 'file', 'max:10240'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests\Messaging;
|
||||||
|
|
||||||
|
use App\Http\Requests\ApiFormRequest;
|
||||||
|
|
||||||
|
class MessageUpdateRequest extends ApiFormRequest
|
||||||
|
{
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'status' => ['nullable', 'in:sent,received,draft,trashed'],
|
||||||
|
'priority' => ['nullable', 'in:low,normal,high'],
|
||||||
|
'read_status' => ['nullable', 'in:0,1'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -16,6 +16,7 @@ class PaypalExecuteRequest extends ApiFormRequest
|
|||||||
return [
|
return [
|
||||||
'payer_id' => ['required', 'string', 'max:100'],
|
'payer_id' => ['required', 'string', 'max:100'],
|
||||||
'paypal_payment_id' => ['nullable', 'string', 'max:100'],
|
'paypal_payment_id' => ['nullable', 'string', 'max:100'],
|
||||||
|
'payment_id' => ['nullable', 'integer', 'min:1'],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests\Preferences;
|
||||||
|
|
||||||
|
use App\Http\Requests\ApiFormRequest;
|
||||||
|
|
||||||
|
class PreferencesIndexRequest extends ApiFormRequest
|
||||||
|
{
|
||||||
|
public function authorize(): bool
|
||||||
|
{
|
||||||
|
return $this->user() !== null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'user_id' => ['nullable', 'integer', 'min:1'],
|
||||||
|
'q' => ['nullable', 'string', 'max:120'],
|
||||||
|
'sort_by' => ['nullable', 'string', 'in:updated_at,created_at,user_id'],
|
||||||
|
'sort_dir' => ['nullable', 'string', 'in:asc,desc'],
|
||||||
|
'page' => ['nullable', 'integer', 'min:1'],
|
||||||
|
'per_page' => ['nullable', 'integer', 'min:1', 'max:200'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests\Preferences;
|
||||||
|
|
||||||
|
use App\Http\Requests\ApiFormRequest;
|
||||||
|
use App\Services\Preferences\PreferencesOptionsService;
|
||||||
|
use Illuminate\Validation\Rule;
|
||||||
|
|
||||||
|
class PreferencesUpsertRequest extends ApiFormRequest
|
||||||
|
{
|
||||||
|
public function authorize(): bool
|
||||||
|
{
|
||||||
|
return $this->user() !== null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
$options = app(PreferencesOptionsService::class);
|
||||||
|
|
||||||
|
return [
|
||||||
|
'receive_email_notifications' => ['nullable', 'boolean'],
|
||||||
|
'receive_sms_notifications' => ['nullable', 'boolean'],
|
||||||
|
'notification_email' => ['nullable', 'boolean'],
|
||||||
|
'notification_sms' => ['nullable', 'boolean'],
|
||||||
|
'theme' => ['nullable', 'string', Rule::in(['light', 'dark'])],
|
||||||
|
'language' => ['nullable', 'string', Rule::in(['en', 'fr', 'es'])],
|
||||||
|
'style_color' => ['nullable', 'string', Rule::in($options->styleOptions())],
|
||||||
|
'menu_color' => ['nullable', 'string', Rule::in($options->menuOptions())],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests\Security;
|
||||||
|
|
||||||
|
use App\Http\Requests\ApiFormRequest;
|
||||||
|
|
||||||
|
class IpBanIndexRequest extends ApiFormRequest
|
||||||
|
{
|
||||||
|
public function authorize(): bool
|
||||||
|
{
|
||||||
|
return $this->user() !== null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'status' => ['nullable', 'string', 'in:all,active'],
|
||||||
|
'search' => ['nullable', 'string', 'max:100'],
|
||||||
|
'sort_by' => ['nullable', 'string', 'in:updated_at,blocked_until,attempts,ip_address,last_attempt_at'],
|
||||||
|
'sort_dir' => ['nullable', 'string', 'in:asc,desc'],
|
||||||
|
'page' => ['nullable', 'integer', 'min:1'],
|
||||||
|
'per_page' => ['nullable', 'integer', 'min:1', 'max:200'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests\Security;
|
||||||
|
|
||||||
|
use App\Http\Requests\ApiFormRequest;
|
||||||
|
use Illuminate\Contracts\Validation\Validator;
|
||||||
|
|
||||||
|
class IpBanRequest extends ApiFormRequest
|
||||||
|
{
|
||||||
|
public function authorize(): bool
|
||||||
|
{
|
||||||
|
return $this->user() !== null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'id' => ['nullable', 'integer', 'min:1'],
|
||||||
|
'ip' => ['nullable', 'ip'],
|
||||||
|
'hours' => ['nullable', 'integer', 'min:1', 'max:720'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function withValidator(Validator $validator): void
|
||||||
|
{
|
||||||
|
$validator->after(function (Validator $validator) {
|
||||||
|
$id = $this->input('id');
|
||||||
|
$ip = $this->input('ip');
|
||||||
|
if (!$id && !$ip) {
|
||||||
|
$validator->errors()->add('id', 'Either id or ip is required.');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests\Security;
|
||||||
|
|
||||||
|
use App\Http\Requests\ApiFormRequest;
|
||||||
|
use Illuminate\Contracts\Validation\Validator;
|
||||||
|
|
||||||
|
class IpUnbanRequest extends ApiFormRequest
|
||||||
|
{
|
||||||
|
public function authorize(): bool
|
||||||
|
{
|
||||||
|
return $this->user() !== null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'id' => ['nullable', 'integer', 'min:1'],
|
||||||
|
'ip' => ['nullable', 'ip'],
|
||||||
|
'all' => ['nullable', 'boolean'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function withValidator(Validator $validator): void
|
||||||
|
{
|
||||||
|
$validator->after(function (Validator $validator) {
|
||||||
|
$id = $this->input('id');
|
||||||
|
$ip = $this->input('ip');
|
||||||
|
$all = filter_var($this->input('all'), FILTER_VALIDATE_BOOLEAN);
|
||||||
|
|
||||||
|
if (!$all && !$id && !$ip) {
|
||||||
|
$validator->errors()->add('id', 'Either id, ip, or all=true is required.');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests\Settings;
|
||||||
|
|
||||||
|
use App\Http\Requests\ApiFormRequest;
|
||||||
|
|
||||||
|
class PolicyShowRequest extends ApiFormRequest
|
||||||
|
{
|
||||||
|
public function authorize(): bool
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'format' => ['nullable', 'in:html'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests\Settings;
|
||||||
|
|
||||||
|
use App\Http\Requests\ApiFormRequest;
|
||||||
|
|
||||||
|
class SettingsUpdateRequest extends ApiFormRequest
|
||||||
|
{
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'site_name' => ['nullable', 'string', 'max:255'],
|
||||||
|
'administrator_email' => ['nullable', 'email', 'max:255'],
|
||||||
|
'timezone' => ['nullable', 'string', 'max:80'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests\Staff;
|
||||||
|
|
||||||
|
use App\Http\Requests\ApiFormRequest;
|
||||||
|
|
||||||
|
class StaffIndexRequest extends ApiFormRequest
|
||||||
|
{
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'page' => ['nullable', 'integer', 'min:1'],
|
||||||
|
'per_page' => ['nullable', 'integer', 'min:1', 'max:100'],
|
||||||
|
'role' => ['nullable', 'string', 'max:100'],
|
||||||
|
'school_year' => ['nullable', 'string', 'max:20'],
|
||||||
|
'semester' => ['nullable', 'string', 'max:20'],
|
||||||
|
'sort_by' => ['nullable', 'in:created_at,lastname,firstname'],
|
||||||
|
'sort_dir' => ['nullable', 'in:asc,desc'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests\Staff;
|
||||||
|
|
||||||
|
use App\Http\Requests\ApiFormRequest;
|
||||||
|
|
||||||
|
class StaffStoreRequest extends ApiFormRequest
|
||||||
|
{
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'user_id' => ['nullable', 'integer', 'min:1'],
|
||||||
|
'firstname' => ['required', 'string', 'max:100'],
|
||||||
|
'lastname' => ['required', 'string', 'max:100'],
|
||||||
|
'email' => ['required', 'email', 'max:150'],
|
||||||
|
'phone' => ['nullable', 'string', 'max:20'],
|
||||||
|
'role_name' => ['required', 'string', 'max:100'],
|
||||||
|
'school_year' => ['nullable', 'string', 'max:20'],
|
||||||
|
'status' => ['nullable', 'string', 'max:40'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests\Staff;
|
||||||
|
|
||||||
|
use App\Http\Requests\ApiFormRequest;
|
||||||
|
|
||||||
|
class StaffUpdateRequest extends ApiFormRequest
|
||||||
|
{
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'firstname' => ['nullable', 'string', 'max:100'],
|
||||||
|
'lastname' => ['nullable', 'string', 'max:100'],
|
||||||
|
'email' => ['nullable', 'email', 'max:150'],
|
||||||
|
'phone' => ['nullable', 'string', 'max:20'],
|
||||||
|
'role_name' => ['nullable', 'string', 'max:100'],
|
||||||
|
'school_year' => ['nullable', 'string', 'max:20'],
|
||||||
|
'status' => ['nullable', 'string', 'max:40'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests\Support;
|
||||||
|
|
||||||
|
use App\Http\Requests\ApiFormRequest;
|
||||||
|
|
||||||
|
class ContactSendRequest extends ApiFormRequest
|
||||||
|
{
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'name' => ['required', 'string', 'min:3', 'max:255'],
|
||||||
|
'email' => ['required', 'email', 'max:255'],
|
||||||
|
'subject' => ['required', 'string', 'min:3', 'max:255'],
|
||||||
|
'message' => ['required', 'string', 'min:10'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests\Support;
|
||||||
|
|
||||||
|
use App\Http\Requests\ApiFormRequest;
|
||||||
|
|
||||||
|
class SupportRequestIndexRequest extends ApiFormRequest
|
||||||
|
{
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'page' => ['nullable', 'integer', 'min:1'],
|
||||||
|
'per_page' => ['nullable', 'integer', 'min:1', 'max:100'],
|
||||||
|
'status' => ['nullable', 'string', 'max:25'],
|
||||||
|
'user_id' => ['nullable', 'integer', 'min:1'],
|
||||||
|
'sort_by' => ['nullable', 'in:created_at,status,subject'],
|
||||||
|
'sort_dir' => ['nullable', 'in:asc,desc'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests\Support;
|
||||||
|
|
||||||
|
use App\Http\Requests\ApiFormRequest;
|
||||||
|
|
||||||
|
class SupportRequestStoreRequest extends ApiFormRequest
|
||||||
|
{
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'subject' => ['required', 'string', 'min:3', 'max:255'],
|
||||||
|
'message' => ['required', 'string', 'min:10'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests\System;
|
||||||
|
|
||||||
|
use App\Http\Requests\ApiFormRequest;
|
||||||
|
|
||||||
|
class NavItemReorderRequest extends ApiFormRequest
|
||||||
|
{
|
||||||
|
public function authorize(): bool
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'orders' => ['required', 'array'],
|
||||||
|
'orders.*' => ['integer'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests\System;
|
||||||
|
|
||||||
|
use App\Http\Requests\ApiFormRequest;
|
||||||
|
|
||||||
|
class NavItemStoreRequest extends ApiFormRequest
|
||||||
|
{
|
||||||
|
public function authorize(): bool
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'id' => ['nullable', 'integer', 'min:1', 'exists:nav_items,id'],
|
||||||
|
'menu_parent_id' => ['nullable', 'integer', 'min:1', 'exists:nav_items,id'],
|
||||||
|
'parent_id' => ['nullable', 'integer', 'min:1', 'exists:nav_items,id'],
|
||||||
|
'label' => ['required', 'string', 'max:255'],
|
||||||
|
'url' => ['nullable', 'string', 'max:255'],
|
||||||
|
'icon_class' => ['nullable', 'string', 'max:255'],
|
||||||
|
'target' => ['nullable', 'string', 'max:50'],
|
||||||
|
'sort_order' => ['nullable', 'integer'],
|
||||||
|
'is_enabled' => ['nullable', 'boolean'],
|
||||||
|
'roles' => ['nullable', 'array'],
|
||||||
|
'roles.*' => ['integer', 'min:1', 'exists:roles,id'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests\Ui;
|
||||||
|
|
||||||
|
use App\Http\Requests\ApiFormRequest;
|
||||||
|
|
||||||
|
class UiStyleRequest extends ApiFormRequest
|
||||||
|
{
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'accent' => ['nullable', 'string', 'max:50'],
|
||||||
|
'menu' => ['nullable', 'string', 'max:50'],
|
||||||
|
'menu_bg' => ['nullable', 'string', 'max:20'],
|
||||||
|
'menu_text' => ['nullable', 'string', 'max:20'],
|
||||||
|
'menu_mode' => ['nullable', 'in:light,dark,auto'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests\Utilities;
|
||||||
|
|
||||||
|
use App\Http\Requests\ApiFormRequest;
|
||||||
|
|
||||||
|
class PhoneFormatRequest extends ApiFormRequest
|
||||||
|
{
|
||||||
|
public function authorize(): bool
|
||||||
|
{
|
||||||
|
return $this->user() !== null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'number' => ['required', 'string', 'max:50'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Resources\Attendance;
|
||||||
|
|
||||||
|
use Illuminate\Http\Resources\Json\ResourceCollection;
|
||||||
|
|
||||||
|
class LateSlipLogCollection extends ResourceCollection
|
||||||
|
{
|
||||||
|
public $collects = LateSlipLogResource::class;
|
||||||
|
|
||||||
|
public function toArray($request): array
|
||||||
|
{
|
||||||
|
return parent::toArray($request);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function with($request): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'meta' => [
|
||||||
|
'total' => $this->resource->total() ?? null,
|
||||||
|
'per_page' => $this->resource->perPage() ?? null,
|
||||||
|
'current_page' => $this->resource->currentPage() ?? null,
|
||||||
|
'last_page' => $this->resource->lastPage() ?? null,
|
||||||
|
],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Resources\Attendance;
|
||||||
|
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Http\Resources\Json\JsonResource;
|
||||||
|
|
||||||
|
class LateSlipLogResource extends JsonResource
|
||||||
|
{
|
||||||
|
public function toArray(Request $request): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'id' => $this->resource->id ?? null,
|
||||||
|
'school_year' => $this->resource->school_year ?? null,
|
||||||
|
'semester' => $this->resource->semester ?? null,
|
||||||
|
'student_name' => $this->resource->student_name ?? null,
|
||||||
|
'slip_date' => $this->resource->slip_date ?? null,
|
||||||
|
'time_in' => $this->resource->time_in ?? null,
|
||||||
|
'grade' => $this->resource->grade ?? null,
|
||||||
|
'reason' => $this->resource->reason ?? null,
|
||||||
|
'admin_name' => $this->resource->admin_name ?? null,
|
||||||
|
'printed_by' => $this->resource->printed_by ?? null,
|
||||||
|
'printed_at' => $this->resource->printed_at ?? null,
|
||||||
|
'created_at' => $this->resource->created_at ?? null,
|
||||||
|
'updated_at' => $this->resource->updated_at ?? null,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Http\Resources\Auth;
|
|
||||||
|
|
||||||
use Illuminate\Http\Resources\Json\JsonResource;
|
|
||||||
|
|
||||||
class SessionTimeoutConfigResource extends JsonResource
|
|
||||||
{
|
|
||||||
public function toArray($request): array
|
|
||||||
{
|
|
||||||
return [
|
|
||||||
'timeout' => (int) ($this['timeout'] ?? 0),
|
|
||||||
'warning_time' => (int) ($this['warning_time'] ?? 0),
|
|
||||||
'check_interval' => (int) ($this['check_interval'] ?? 0),
|
|
||||||
'logout_url' => (string) ($this['logout_url'] ?? ''),
|
|
||||||
'keep_alive_url' => (string) ($this['keep_alive_url'] ?? ''),
|
|
||||||
'check_url' => (string) ($this['check_url'] ?? ''),
|
|
||||||
];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Http\Resources\Auth;
|
|
||||||
|
|
||||||
use Illuminate\Http\Resources\Json\JsonResource;
|
|
||||||
|
|
||||||
class SessionTimeoutStatusResource extends JsonResource
|
|
||||||
{
|
|
||||||
public function toArray($request): array
|
|
||||||
{
|
|
||||||
return [
|
|
||||||
'status' => (string) ($this['status'] ?? ''),
|
|
||||||
'time_remaining' => (int) ($this['time_remaining'] ?? 0),
|
|
||||||
'redirect' => $this['redirect'] ?? null,
|
|
||||||
'message' => $this['message'] ?? null,
|
|
||||||
];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Resources\ClassPreparation;
|
||||||
|
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Http\Resources\Json\JsonResource;
|
||||||
|
|
||||||
|
class ClassPreparationPrintResource extends JsonResource
|
||||||
|
{
|
||||||
|
public function toArray(Request $request): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'class_section_id' => $this->resource['class_section_id'] ?? null,
|
||||||
|
'class_section' => $this->resource['class_section'] ?? null,
|
||||||
|
'school_year' => $this->resource['school_year'] ?? null,
|
||||||
|
'semester' => $this->resource['semester'] ?? null,
|
||||||
|
'prep_items' => $this->resource['prep_items'] ?? [],
|
||||||
|
'adjustments' => $this->resource['adjustments'] ?? [],
|
||||||
|
'printed_at' => $this->resource['printed_at'] ?? null,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Resources\ClassPreparation;
|
||||||
|
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Http\Resources\Json\JsonResource;
|
||||||
|
|
||||||
|
class ClassPreparationResultResource extends JsonResource
|
||||||
|
{
|
||||||
|
public function toArray(Request $request): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'class_section' => $this->resource['class_section'] ?? null,
|
||||||
|
'class_section_id' => $this->resource['class_section_id'] ?? null,
|
||||||
|
'student_count' => $this->resource['student_count'] ?? 0,
|
||||||
|
'class_level' => $this->resource['class_level'] ?? null,
|
||||||
|
'prep_items' => $this->resource['prep_items'] ?? [],
|
||||||
|
'needs_print' => $this->resource['needs_print'] ?? false,
|
||||||
|
'last_printed_at' => $this->resource['last_printed_at'] ?? null,
|
||||||
|
'adjustments' => $this->resource['adjustments'] ?? [],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Resources\Classes;
|
||||||
|
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Http\Resources\Json\JsonResource;
|
||||||
|
|
||||||
|
class ClassAttendanceResource extends JsonResource
|
||||||
|
{
|
||||||
|
public function toArray(Request $request): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'teacher_name' => $this->resource['teacher_name'] ?? null,
|
||||||
|
'class_name' => $this->resource['class_name'] ?? null,
|
||||||
|
'class_section_id' => $this->resource['class_section_id'] ?? null,
|
||||||
|
'semester' => $this->resource['semester'] ?? null,
|
||||||
|
'school_year' => $this->resource['school_year'] ?? null,
|
||||||
|
'students' => ClassAttendanceStudentResource::collection($this->resource['students'] ?? []),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Resources\Classes;
|
||||||
|
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Http\Resources\Json\JsonResource;
|
||||||
|
|
||||||
|
class ClassAttendanceStudentResource extends JsonResource
|
||||||
|
{
|
||||||
|
public function toArray(Request $request): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'student_id' => $this->resource['student_id'] ?? null,
|
||||||
|
'school_id' => $this->resource['school_id'] ?? null,
|
||||||
|
'firstname' => $this->resource['firstname'] ?? null,
|
||||||
|
'lastname' => $this->resource['lastname'] ?? null,
|
||||||
|
'class_section_id' => $this->resource['class_section_id'] ?? null,
|
||||||
|
'updated_by' => $this->resource['updated_by'] ?? null,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Resources\Classes;
|
||||||
|
|
||||||
|
use Illuminate\Http\Resources\Json\ResourceCollection;
|
||||||
|
|
||||||
|
class ClassSectionCollection extends ResourceCollection
|
||||||
|
{
|
||||||
|
public $collects = ClassSectionResource::class;
|
||||||
|
|
||||||
|
public function toArray($request): array
|
||||||
|
{
|
||||||
|
return parent::toArray($request);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function with($request): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'meta' => [
|
||||||
|
'total' => $this->resource->total() ?? null,
|
||||||
|
'per_page' => $this->resource->perPage() ?? null,
|
||||||
|
'current_page' => $this->resource->currentPage() ?? null,
|
||||||
|
'last_page' => $this->resource->lastPage() ?? null,
|
||||||
|
],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Resources\Classes;
|
||||||
|
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Http\Resources\Json\JsonResource;
|
||||||
|
|
||||||
|
class ClassSectionResource extends JsonResource
|
||||||
|
{
|
||||||
|
public function toArray(Request $request): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'id' => $this->resource->id ?? null,
|
||||||
|
'class_id' => $this->resource->class_id ?? null,
|
||||||
|
'class_section_id' => $this->resource->class_section_id ?? null,
|
||||||
|
'class_section_name' => $this->resource->class_section_name ?? null,
|
||||||
|
'class_name' => $this->resource->class_name ?? null,
|
||||||
|
'semester' => $this->resource->semester ?? null,
|
||||||
|
'school_year' => $this->resource->school_year ?? null,
|
||||||
|
'created_at' => $this->resource->created_at ?? null,
|
||||||
|
'updated_at' => $this->resource->updated_at ?? null,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Resources\Frontend;
|
||||||
|
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Http\Resources\Json\JsonResource;
|
||||||
|
|
||||||
|
class ContactSubmissionResource extends JsonResource
|
||||||
|
{
|
||||||
|
public function toArray(Request $request): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'email' => $this->resource['email'] ?? null,
|
||||||
|
'email_sent' => (bool) ($this->resource['email_sent'] ?? false),
|
||||||
|
'contact_id' => $this->resource['contact_id'] ?? null,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Resources\Frontend;
|
||||||
|
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Http\Resources\Json\JsonResource;
|
||||||
|
|
||||||
|
class FrontendPageResource extends JsonResource
|
||||||
|
{
|
||||||
|
public function toArray(Request $request): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'page' => $this->resource['page'] ?? null,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Resources\Frontend;
|
||||||
|
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Http\Resources\Json\JsonResource;
|
||||||
|
|
||||||
|
class FrontendUserResource extends JsonResource
|
||||||
|
{
|
||||||
|
public function toArray(Request $request): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'firstname' => $this->firstname ?? null,
|
||||||
|
'lastname' => $this->lastname ?? null,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Resources\Frontend;
|
||||||
|
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Http\Resources\Json\JsonResource;
|
||||||
|
|
||||||
|
class LandingPageResource extends JsonResource
|
||||||
|
{
|
||||||
|
public function toArray(Request $request): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'role' => $this->resource['role'] ?? null,
|
||||||
|
'dashboard' => $this->resource['dashboard'] ?? null,
|
||||||
|
'summary' => $this->resource['summary'] ?? null,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Resources\Frontend;
|
||||||
|
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Http\Resources\Json\JsonResource;
|
||||||
|
|
||||||
|
class PageContentResource extends JsonResource
|
||||||
|
{
|
||||||
|
public function toArray(Request $request): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'type' => $this->resource['type'] ?? null,
|
||||||
|
'content' => $this->resource['content'] ?? null,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Resources\Frontend;
|
||||||
|
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Http\Resources\Json\JsonResource;
|
||||||
|
|
||||||
|
class ProfileIconResource extends JsonResource
|
||||||
|
{
|
||||||
|
public function toArray(Request $request): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'user_name' => $this->resource['userName'] ?? null,
|
||||||
|
'user_initials' => $this->resource['userInitials'] ?? null,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Resources\Messaging;
|
||||||
|
|
||||||
|
use Illuminate\Http\Resources\Json\ResourceCollection;
|
||||||
|
|
||||||
|
class MessageCollection extends ResourceCollection
|
||||||
|
{
|
||||||
|
public function with($request): array
|
||||||
|
{
|
||||||
|
if (!method_exists($this->resource, 'total')) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
return [
|
||||||
|
'meta' => [
|
||||||
|
'total' => $this->resource->total() ?? null,
|
||||||
|
'per_page' => $this->resource->perPage() ?? null,
|
||||||
|
'current_page' => $this->resource->currentPage() ?? null,
|
||||||
|
'last_page' => $this->resource->lastPage() ?? null,
|
||||||
|
],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function toArray($request): array
|
||||||
|
{
|
||||||
|
return $this->collection->map(function ($item) use ($request) {
|
||||||
|
return (new MessageResource($item))->toArray($request);
|
||||||
|
})->all();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Resources\Messaging;
|
||||||
|
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Http\Resources\Json\JsonResource;
|
||||||
|
|
||||||
|
class MessageResource extends JsonResource
|
||||||
|
{
|
||||||
|
public function toArray(Request $request): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'id' => $this->id ?? null,
|
||||||
|
'sender_id' => $this->sender_id ?? null,
|
||||||
|
'recipient_id' => $this->recipient_id ?? null,
|
||||||
|
'subject' => $this->subject ?? null,
|
||||||
|
'message' => $this->message ?? null,
|
||||||
|
'sent_datetime' => optional($this->sent_datetime)->toDateTimeString(),
|
||||||
|
'read_status' => (bool) ($this->read_status ?? false),
|
||||||
|
'read_datetime' => optional($this->read_datetime)->toDateTimeString(),
|
||||||
|
'message_number' => $this->message_number ?? null,
|
||||||
|
'priority' => $this->priority ?? null,
|
||||||
|
'attachment' => $this->attachment ?? null,
|
||||||
|
'status' => $this->status ?? null,
|
||||||
|
'semester' => $this->semester ?? null,
|
||||||
|
'school_year' => $this->school_year ?? null,
|
||||||
|
'sender_name' => $this->sender ? trim($this->sender->firstname . ' ' . $this->sender->lastname) : null,
|
||||||
|
'recipient_name' => $this->recipient ? trim($this->recipient->firstname . ' ' . $this->recipient->lastname) : null,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Resources\Messaging;
|
||||||
|
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Http\Resources\Json\JsonResource;
|
||||||
|
|
||||||
|
class RecipientResource extends JsonResource
|
||||||
|
{
|
||||||
|
public function toArray(Request $request): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'id' => $this->resource['id'] ?? null,
|
||||||
|
'name' => $this->resource['name'] ?? null,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Resources\Preferences;
|
||||||
|
|
||||||
|
use Illuminate\Http\Resources\Json\ResourceCollection;
|
||||||
|
|
||||||
|
class PreferencesCollection extends ResourceCollection
|
||||||
|
{
|
||||||
|
public $collects = PreferencesListResource::class;
|
||||||
|
|
||||||
|
public function toArray($request): array
|
||||||
|
{
|
||||||
|
return parent::toArray($request);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function with($request): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'meta' => [
|
||||||
|
'total' => $this->resource->total() ?? null,
|
||||||
|
'per_page' => $this->resource->perPage() ?? null,
|
||||||
|
'current_page' => $this->resource->currentPage() ?? null,
|
||||||
|
'last_page' => $this->resource->lastPage() ?? null,
|
||||||
|
],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Resources\Preferences;
|
||||||
|
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Http\Resources\Json\JsonResource;
|
||||||
|
|
||||||
|
class PreferencesListResource extends JsonResource
|
||||||
|
{
|
||||||
|
public function toArray(Request $request): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'id' => $this->resource->id ?? null,
|
||||||
|
'user_id' => $this->resource->user_id ?? null,
|
||||||
|
'firstname' => $this->resource->firstname ?? null,
|
||||||
|
'lastname' => $this->resource->lastname ?? null,
|
||||||
|
'email' => $this->resource->email ?? null,
|
||||||
|
'receive_email_notifications' => (bool) ($this->resource->notification_email ?? false),
|
||||||
|
'receive_sms_notifications' => (bool) ($this->resource->notification_sms ?? false),
|
||||||
|
'theme' => $this->resource->theme ?? null,
|
||||||
|
'language' => $this->resource->language ?? null,
|
||||||
|
'style_color' => $this->resource->style_color ?? null,
|
||||||
|
'menu_color' => $this->resource->menu_color ?? null,
|
||||||
|
'created_at' => $this->resource->created_at ?? null,
|
||||||
|
'updated_at' => $this->resource->updated_at ?? null,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Resources\Preferences;
|
||||||
|
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Http\Resources\Json\JsonResource;
|
||||||
|
|
||||||
|
class PreferencesResource extends JsonResource
|
||||||
|
{
|
||||||
|
public function toArray(Request $request): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'receive_email_notifications' => $this->resource['receive_email_notifications'] ?? false,
|
||||||
|
'receive_sms_notifications' => $this->resource['receive_sms_notifications'] ?? false,
|
||||||
|
'theme' => $this->resource['theme'] ?? null,
|
||||||
|
'language' => $this->resource['language'] ?? null,
|
||||||
|
'style_color' => $this->resource['style_color'] ?? null,
|
||||||
|
'menu_color' => $this->resource['menu_color'] ?? null,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Resources\Security;
|
||||||
|
|
||||||
|
use Illuminate\Http\Resources\Json\ResourceCollection;
|
||||||
|
|
||||||
|
class IpBanCollection extends ResourceCollection
|
||||||
|
{
|
||||||
|
public $collects = IpBanResource::class;
|
||||||
|
|
||||||
|
public function toArray($request): array
|
||||||
|
{
|
||||||
|
return parent::toArray($request);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function with($request): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'meta' => [
|
||||||
|
'total' => $this->resource->total() ?? null,
|
||||||
|
'per_page' => $this->resource->perPage() ?? null,
|
||||||
|
'current_page' => $this->resource->currentPage() ?? null,
|
||||||
|
'last_page' => $this->resource->lastPage() ?? null,
|
||||||
|
],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Resources\Security;
|
||||||
|
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Http\Resources\Json\JsonResource;
|
||||||
|
|
||||||
|
class IpBanResource extends JsonResource
|
||||||
|
{
|
||||||
|
public function toArray(Request $request): array
|
||||||
|
{
|
||||||
|
$blockedUntil = $this->resource->blocked_until ?? null;
|
||||||
|
$isActive = $blockedUntil !== null && $blockedUntil > now('UTC');
|
||||||
|
|
||||||
|
return [
|
||||||
|
'id' => $this->resource->id ?? null,
|
||||||
|
'ip_address' => $this->resource->ip_address ?? null,
|
||||||
|
'attempts' => $this->resource->attempts ?? 0,
|
||||||
|
'last_attempt_at' => $this->resource->last_attempt_at ?? null,
|
||||||
|
'blocked_until' => $blockedUntil,
|
||||||
|
'is_active' => $isActive,
|
||||||
|
'created_at' => $this->resource->created_at ?? null,
|
||||||
|
'updated_at' => $this->resource->updated_at ?? null,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Resources\Settings;
|
||||||
|
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Http\Resources\Json\JsonResource;
|
||||||
|
|
||||||
|
class PolicyResource extends JsonResource
|
||||||
|
{
|
||||||
|
public function toArray(Request $request): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'type' => $this->resource['type'] ?? null,
|
||||||
|
'title' => $this->resource['title'] ?? null,
|
||||||
|
'format' => $this->resource['format'] ?? 'html',
|
||||||
|
'content' => $this->resource['content'] ?? '',
|
||||||
|
'updated_at' => $this->resource['updated_at'] ?? null,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Resources\Settings;
|
||||||
|
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Http\Resources\Json\JsonResource;
|
||||||
|
|
||||||
|
class SettingsResource extends JsonResource
|
||||||
|
{
|
||||||
|
public function toArray(Request $request): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'site_name' => $this->resource['site_name'] ?? null,
|
||||||
|
'administrator_email' => $this->resource['administrator_email'] ?? null,
|
||||||
|
'timezone' => $this->resource['timezone'] ?? null,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Resources\Staff;
|
||||||
|
|
||||||
|
use Illuminate\Http\Resources\Json\ResourceCollection;
|
||||||
|
|
||||||
|
class StaffCollection extends ResourceCollection
|
||||||
|
{
|
||||||
|
public function toArray($request): array
|
||||||
|
{
|
||||||
|
return $this->collection->map(function ($item) use ($request) {
|
||||||
|
return (new StaffResource($item))->toArray($request);
|
||||||
|
})->all();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function with($request): array
|
||||||
|
{
|
||||||
|
if (!method_exists($this->resource, 'total')) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
return [
|
||||||
|
'meta' => [
|
||||||
|
'total' => $this->resource->total() ?? null,
|
||||||
|
'per_page' => $this->resource->perPage() ?? null,
|
||||||
|
'current_page' => $this->resource->currentPage() ?? null,
|
||||||
|
'last_page' => $this->resource->lastPage() ?? null,
|
||||||
|
],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Resources\Staff;
|
||||||
|
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Http\Resources\Json\JsonResource;
|
||||||
|
|
||||||
|
class StaffResource extends JsonResource
|
||||||
|
{
|
||||||
|
public function toArray(Request $request): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'id' => $this->id ?? null,
|
||||||
|
'user_id' => $this->user_id ?? null,
|
||||||
|
'firstname' => $this->firstname ?? null,
|
||||||
|
'lastname' => $this->lastname ?? null,
|
||||||
|
'email' => $this->email ?? null,
|
||||||
|
'phone' => $this->phone ?? null,
|
||||||
|
'role_name' => $this->role_name ?? null,
|
||||||
|
'active_role' => $this->active_role ?? null,
|
||||||
|
'school_year' => $this->school_year ?? null,
|
||||||
|
'class_section' => $this->class_section ?? null,
|
||||||
|
'verification_issue' => (bool) ($this->verification_issue ?? false),
|
||||||
|
'school_id' => $this->school_id ?? null,
|
||||||
|
'created_at' => optional($this->created_at)->toDateTimeString(),
|
||||||
|
'updated_at' => optional($this->updated_at)->toDateTimeString(),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Resources\Support;
|
||||||
|
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Http\Resources\Json\JsonResource;
|
||||||
|
|
||||||
|
class ContactMessageResource extends JsonResource
|
||||||
|
{
|
||||||
|
public function toArray(Request $request): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'email_sent' => (bool) ($this->resource['email_sent'] ?? false),
|
||||||
|
'recipient' => $this->resource['recipient'] ?? null,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Resources\Support;
|
||||||
|
|
||||||
|
use Illuminate\Http\Resources\Json\ResourceCollection;
|
||||||
|
|
||||||
|
class SupportRequestCollection extends ResourceCollection
|
||||||
|
{
|
||||||
|
public function toArray($request): array
|
||||||
|
{
|
||||||
|
return $this->collection->map(function ($item) use ($request) {
|
||||||
|
return (new SupportRequestResource($item))->toArray($request);
|
||||||
|
})->all();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function with($request): array
|
||||||
|
{
|
||||||
|
if (!method_exists($this->resource, 'total')) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
return [
|
||||||
|
'meta' => [
|
||||||
|
'total' => $this->resource->total() ?? null,
|
||||||
|
'per_page' => $this->resource->perPage() ?? null,
|
||||||
|
'current_page' => $this->resource->currentPage() ?? null,
|
||||||
|
'last_page' => $this->resource->lastPage() ?? null,
|
||||||
|
],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Resources\Support;
|
||||||
|
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Http\Resources\Json\JsonResource;
|
||||||
|
|
||||||
|
class SupportRequestResource extends JsonResource
|
||||||
|
{
|
||||||
|
public function toArray(Request $request): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'id' => $this->id ?? null,
|
||||||
|
'user_id' => $this->user_id ?? null,
|
||||||
|
'subject' => $this->subject ?? null,
|
||||||
|
'message' => $this->message ?? null,
|
||||||
|
'status' => $this->status ?? null,
|
||||||
|
'semester' => $this->semester ?? null,
|
||||||
|
'school_year' => $this->school_year ?? null,
|
||||||
|
'created_at' => optional($this->created_at)->toDateTimeString(),
|
||||||
|
'updated_at' => optional($this->updated_at)->toDateTimeString(),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Resources\System;
|
||||||
|
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Http\Resources\Json\JsonResource;
|
||||||
|
|
||||||
|
class DashboardRouteResource extends JsonResource
|
||||||
|
{
|
||||||
|
public function toArray(Request $request): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'route' => $this->resource['route'] ?? null,
|
||||||
|
'role' => $this->resource['role'] ?? null,
|
||||||
|
'role_slug' => $this->resource['role_slug'] ?? null,
|
||||||
|
'roles' => $this->resource['roles'] ?? [],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user