@extends('layouts.app') @section('title', 'Информация о группе') {{-- Ports app/Views/group/show.php (legacy, 1450 lines) + the render() payload from App\Controllers\GroupController::show() (app/Controllers/GroupController.php:488-559) — see the Phase 16 plan. Every write form on this page is Laravel-native @csrf as of Phase 21 (edit/delete/deactivate-group: Phase 17; group-tariff CRUD: Phase 18; schedule CRUD: Phase 19; student add/remove: Phase 21, shared with adviser/schedule/index.blade.php since that page migrated in Phase 20). No more legacy CSRF pass-through forms remain on this page. The edit-group modal checks Laravel's own $errors/old() first (set by Illuminate\Http\Request::validate()'s automatic redirect-back), falling back to the legacy $oldInput/$oldErrors (Phase 16) only when Laravel's own bag is empty — the two can never both be populated for the same request/redirect cycle, since only one side ever writes on any given submit. See the Phase 17 plan. Role gating mirrors the legacy view's two in_array($role, ['admin']) blocks exactly (tariffs, financials) — the page itself has no page-level role restriction (only SessionAuth::check()), matching the same flagged-not-fixed ambiguity as student_admin_info.php. The #StudentModal edit-student-in-group form is ported byte-for-byte broken, matching production: it posts to /update_student_to_group.php (no matching route at all) and its data-weekdays attribute is always empty (Group::getStudents() never selects sg.weekdays) — not this phase's concern to fix. --}} @push('styles') @endpush @php $editGroupHasError = $errors->any() || isset($oldErrors['group_name']) || isset($oldErrors['teacher_id']) || isset($oldErrors['group_type']) || isset($oldErrors['subject_id']) || isset($oldErrors['language_id']) || isset($oldErrors['learning_type_id']) || isset($oldErrors['class_id']); $editGroupError = fn (string $field) => $errors->first($field) ?: ($oldErrors[$field] ?? null); $editGroupOld = fn (string $field, string $default = '') => $errors->any() ? old($field, $default) : ($oldInput[$field] ?? $default); @endphp @section('content')
@if ($group !== null)
Общая информация
{{ mb_strtoupper(mb_substr($group->group_name, 0, 2)) }}

{{ $group->group_name }}

Преподаватель
{{ $group->teacher_name ?? '—' }}
Тип
{{ $group->type }}
Класс
{{ $group->class_name ?? '—' }}
Предмет
{{ $group->discipline_name ?? '—' }}
Язык
{{ $group->language_name ?? '—' }}
Тип обучения
{{ $group->learning_type_name ?? '—' }}
@endif
Студенты
    @if (!empty($localStudents)) @foreach ($localStudents as $student)
  • {{ trim("{$student->last_name} {$student->first_name}") }}
    @csrf
  • @endforeach @else

    В этой группе нет студентов в локальной базе данных.

    @endif
{{-- Legacy form has no CSRF field at all here (matches production — see the class docblock). --}}
Расписание
    @if (!empty($localSchedule)) @foreach ($localSchedule as $schedule)
  • Время: {{ date('H:i', strtotime($schedule->begin_time)) }} - {{ date('H:i', strtotime($schedule->end_time)) }}
    Дни: {{ \App\Support\Weekdays::toString((int) $schedule->weekdays) }}
    С: {{ $schedule->begin_date }} @if (!empty($schedule->end_date)) по {{ $schedule->end_date }} @endif
    @if (!empty($schedule->classroom_name)) Кабинет: {{ $schedule->classroom_name }}
    @endif @if (!empty($schedule->classroom_link)) Ссылка на кабинет @endif
    @csrf
  • @endforeach @else

    Расписание в локальной базе не найдено.

    @endif
@if (in_array($role, ['admin'], true))
Тарифы группы
    @if (!empty($groupTariffs)) @foreach ($groupTariffs as $gt) @php $isActive = $gt->start_date <= date('Y-m-d') && $gt->end_date >= date('Y-m-d'); $chargePerLesson = $gt->lessons_count > 0 ? number_format($gt->price / $gt->lessons_count, 2) : '—'; $displayName = preg_replace('/^\[manual\]\s*/', '', $gt->name); @endphp
  • {{ $displayName }} @if ($gt->is_manual) Ручной @endif @if ($isActive) Активен @else Неактивен @endif
    Цена: {{ number_format((float) $gt->price, 2) }}  |  Уроков: {{ $gt->lessons_count }}  |  За урок: {{ $chargePerLesson }}
    С: {{ $gt->start_date }} по {{ $gt->end_date }}
    @csrf
  • @endforeach @else

    Тарифы для группы не назначены.

    @endif
@endif @if (in_array($role, ['admin'], true))
Финансы группы
@if (!$financials['has_tariff'])
Нет активного тарифа — расчёт невозможен.
@endif @if ($financials['student_count'] === 0)
В группе нет активных студентов.
@endif
За один урок
Студентов
{{ $financials['student_count'] }}
Выручка
{{ number_format($financials['gross_per_lesson'], 0, '.', ' ') }}
{{ number_format($financials['revenue_per_lesson'], 0, '.', ' ') }} × {{ $financials['student_count'] }}
Расходы
{{ number_format($financials['costs_per_lesson'], 0, '.', ' ') }}
учитель {{ number_format($financials['teacher_price'], 0, '.', ' ') }} + аренда {{ number_format($financials['rent_per_lesson'], 0, '.', ' ') }}
Прибыль
{{ number_format($financials['profit_per_lesson'], 0, '.', ' ') }}
маржа {{ $financials['margin'] }}%

Текущий месяц {{ $financials['lessons_this_month'] }} уроков
Начислено
{{ number_format($financials['charged_this_month'], 0, '.', ' ') }}
Учитель
{{ number_format($financials['teacher_cost_month'], 0, '.', ' ') }}
Аренда
{{ number_format($financials['rent_cost_month'], 0, '.', ' ') }}
Прибыль
{{ number_format($financials['profit_this_month'], 0, '.', ' ') }}

Прогноз месяца {{ $financials['predicted_lessons'] }} уроков
Начислено
{{ number_format($financials['predicted_charged'], 0, '.', ' ') }}
Учитель
{{ number_format($financials['predicted_teacher_cost'], 0, '.', ' ') }}
Аренда
{{ number_format($financials['predicted_rent_cost'], 0, '.', ' ') }}
Прибыль
{{ number_format($financials['predicted_profit'], 0, '.', ' ') }}
@endif
@endsection @push('scripts') {{-- Legacy page loads jQuery itself for the $.ajax student-search autocomplete and $(...).on(...) handlers below — the shared layout doesn't include it. --}} @endpush