222 lines
7.5 KiB
PHP
222 lines
7.5 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Http\Controllers;
|
|
|
|
use App\Repositories\StudentTenantRepository;
|
|
use App\Repositories\AppointmentRequestRepository;
|
|
use App\Repositories\InstructorAvailabilityRepository;
|
|
use App\Repositories\InstructorRepository;
|
|
use App\Repositories\StudentRepository;
|
|
use App\Support\Auth;
|
|
use App\Support\Request;
|
|
use App\Support\Response;
|
|
|
|
final class StudentController
|
|
{
|
|
private StudentTenantRepository $studentTenantRepo;
|
|
private AppointmentRequestRepository $requestRepo;
|
|
private InstructorAvailabilityRepository $availRepo;
|
|
private InstructorRepository $instructorRepo;
|
|
private StudentRepository $studentRepo;
|
|
|
|
public function __construct()
|
|
{
|
|
$this->studentTenantRepo = new StudentTenantRepository();
|
|
$this->requestRepo = new AppointmentRequestRepository();
|
|
$this->availRepo = new InstructorAvailabilityRepository();
|
|
$this->instructorRepo = new InstructorRepository();
|
|
$this->studentRepo = new StudentRepository();
|
|
}
|
|
|
|
/**
|
|
* GET /api/v1/student/me
|
|
*/
|
|
public function me(Request $request): void
|
|
{
|
|
$user = Auth::requireRole(['student']);
|
|
|
|
$tenants = $this->studentTenantRepo->getActiveForUser((int) $user['id']);
|
|
|
|
Response::json([
|
|
'user' => [
|
|
'id' => (int) $user['id'],
|
|
'email' => $user['email'],
|
|
'first_name' => $user['first_name'],
|
|
'last_name' => $user['last_name'],
|
|
'role' => $user['role'],
|
|
],
|
|
'tenants' => $tenants,
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* GET /api/v1/student/instructors?tenant_id=X
|
|
* Liste aller Fahrlehrer einer Fahrschule (mit Kalender-Sichtbarkeit)
|
|
*/
|
|
public function instructors(Request $request): void
|
|
{
|
|
$user = Auth::requireRole(['student']);
|
|
$tenantId = (int) ($request->query('tenant_id') ?? $user['tenant_id']);
|
|
|
|
// Prüfe ob Student Zugriff auf diesen Tenant hat
|
|
$st = $this->studentTenantRepo->findByUserAndTenant((int) $user['id'], $tenantId);
|
|
if ($st === null || $st['status'] !== 'active') {
|
|
Response::json(['message' => 'Kein Zugriff auf diese Fahrschule'], 403);
|
|
}
|
|
|
|
$instructors = $this->instructorRepo->listForTenant($tenantId);
|
|
|
|
$result = [];
|
|
foreach ($instructors as $i) {
|
|
if ($i['is_active'] !== 1 || $i['booking_enabled'] !== 1) {
|
|
continue;
|
|
}
|
|
$result[] = [
|
|
'id' => $i['id'],
|
|
'first_name' => $i['first_name'],
|
|
'last_name' => $i['last_name'],
|
|
'color' => $i['color'] ?? '#3b82f6',
|
|
];
|
|
}
|
|
|
|
Response::json(['data' => $result]);
|
|
}
|
|
|
|
/**
|
|
* GET /api/v1/student/instructors/{id}/slots?from=&to=&tenant_id=X
|
|
* Belegte Slots für einen Fahrlehrer (was der Fahrschüler sehen darf)
|
|
*/
|
|
public function instructorSlots(Request $request, array $params): void
|
|
{
|
|
$user = Auth::requireRole(['student']);
|
|
$instructorId = (int) $params['id'];
|
|
$from = (string) ($request->query('from') ?? date('Y-m-d'));
|
|
$to = (string) ($request->query('to') ?? date('Y-m-d', strtotime('+30 days')));
|
|
$tenantId = (int) ($request->query('tenant_id') ?? $user['tenant_id']);
|
|
|
|
// Zugriff prüfen
|
|
$st = $this->studentTenantRepo->findByUserAndTenant((int) $user['id'], $tenantId);
|
|
if ($st === null || $st['status'] !== 'active') {
|
|
Response::json(['message' => 'Kein Zugriff'], 403);
|
|
}
|
|
|
|
// Instructor existiert?
|
|
$instructor = $this->instructorRepo->findById($instructorId);
|
|
if ($instructor === null) {
|
|
Response::json(['message' => 'Fahrlehrer nicht gefunden'], 404);
|
|
}
|
|
|
|
// Availability holen
|
|
$availability = $this->availRepo->getActiveForInstructor($instructorId);
|
|
|
|
Response::json([
|
|
'instructor' => [
|
|
'id' => $instructor['id'],
|
|
'first_name' => $instructor['first_name'],
|
|
'last_name' => $instructor['last_name'],
|
|
],
|
|
'availability' => $availability,
|
|
'from' => $from,
|
|
'to' => $to,
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* POST /api/v1/student/appointment-requests
|
|
* Neue Terminanfrage eines Fahrschülers
|
|
*/
|
|
public function createAppointmentRequest(Request $request): void
|
|
{
|
|
$user = Auth::requireRole(['student']);
|
|
$payload = $request->input();
|
|
|
|
$instructorId = (int) ($payload['instructor_id'] ?? 0);
|
|
$lessonTypeId = (int) ($payload['lesson_type_id'] ?? 0);
|
|
$start = trim((string) ($payload['start'] ?? ''));
|
|
$end = trim((string) ($payload['end'] ?? ''));
|
|
$notes = trim((string) ($payload['notes'] ?? ''));
|
|
$tenantId = (int) ($payload['tenant_id'] ?? $user['tenant_id']);
|
|
|
|
if ($instructorId <= 0 || $lessonTypeId <= 0 || $start === '' || $end === '') {
|
|
Response::json(['message' => 'instructor_id, lesson_type_id, start und end sind erforderlich'], 422);
|
|
}
|
|
|
|
// Tenant-Zugriff prüfen
|
|
$st = $this->studentTenantRepo->findByUserAndTenant((int) $user['id'], $tenantId);
|
|
if ($st === null || $st['status'] !== 'active') {
|
|
Response::json(['message' => 'Kein Zugriff auf diese Fahrschule'], 403);
|
|
}
|
|
|
|
// Instructor prüfen
|
|
$instructor = $this->instructorRepo->findById($instructorId);
|
|
if ($instructor === null) {
|
|
Response::json(['message' => 'Fahrlehrer nicht gefunden'], 404);
|
|
}
|
|
|
|
if ($instructor['booking_enabled'] !== 1) {
|
|
Response::json(['message' => 'Dieser Fahrlehrer akzeptiert keine Anfragen'], 400);
|
|
}
|
|
|
|
// Anfrage erstellen
|
|
$record = $this->requestRepo->create(
|
|
(int) $user['id'],
|
|
$instructorId,
|
|
$lessonTypeId,
|
|
$start,
|
|
$end,
|
|
$notes
|
|
);
|
|
|
|
Response::json(['data' => $record], 201);
|
|
}
|
|
|
|
/**
|
|
* GET /api/v1/student/appointment-requests
|
|
*/
|
|
public function appointmentRequests(Request $request): void
|
|
{
|
|
$user = Auth::requireRole(['student']);
|
|
$requests = $this->requestRepo->getForStudent((int) $user['id']);
|
|
|
|
Response::json(['data' => $requests]);
|
|
}
|
|
|
|
/**
|
|
* POST /api/v1/student/add-tenant
|
|
* Fahrschüler gibt neuen Code ein → neuer pending tenant
|
|
*/
|
|
public function addTenant(Request $request): void
|
|
{
|
|
$user = Auth::requireRole(['student']);
|
|
$payload = $request->input();
|
|
$code = trim((string) ($payload['code'] ?? ''));
|
|
|
|
if ($code === '') {
|
|
Response::json(['message' => 'code ist erforderlich'], 422);
|
|
}
|
|
|
|
// Code → Tenant finden
|
|
$tenantRepo = new \App\Repositories\TenantRegistrationCodeRepository();
|
|
$tenantCode = $tenantRepo->findByCode($code);
|
|
if ($tenantCode === null) {
|
|
Response::json(['message' => 'Ungültiger Code'], 400);
|
|
}
|
|
|
|
$tenantId = (int) $tenantCode['tenant_id'];
|
|
|
|
// Already connected?
|
|
$existing = $this->studentTenantRepo->findByUserAndTenant((int) $user['id'], $tenantId);
|
|
if ($existing !== null) {
|
|
Response::json(['message' => 'Du bist bereits mit dieser Fahrschule verbunden'], 400);
|
|
}
|
|
|
|
$record = $this->studentTenantRepo->create((int) $user['id'], $tenantId, 'pending');
|
|
|
|
Response::json([
|
|
'data' => $record,
|
|
'message' => 'Anfrage gesendet, warte auf Bestätigung durch die Fahrschule',
|
|
], 201);
|
|
}
|
|
} |