Files
drivetimeplaner/www/api.fahrschultermin.de/app/Http/Controllers/StudentController.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);
}
}