Система внутренней отчётности и управления для компьютерного клуба.
Роли: Администратор (admin) и Руководитель (manager).
Репозиторий: github.com/Kalekakektop2/admin-calendar
Деплой: Vercel (автоматически при push в main)
| Слой | Технологии |
|---|---|
| Frontend | Next.js 16 (App Router), React 19, TypeScript, Tailwind CSS 4 |
| Backend / Auth / DB | Supabase (PostgreSQL, Auth, Storage, RLS) |
| UI | Lucide React |
| Даты | date-fns (+ локаль ru) |
| Раздел | URL | Описание |
|---|---|---|
| Все смены за месяц | /manager |
Статистика + таблица закрытых отчётов за месяц (без календаря) |
| Календарь смен | /manager/shift-calendar |
Выставление смен админам (день/ночь), цвета админов, режим редактирования |
| Закрытые смены | /manager/closed-shifts |
Только смены, которые были запланированы и закрыты админом; фильтр по администратору |
| Месячные отчёты | /manager/monthly-reports |
Сводка по месяцу |
| Зарплаты | /manager/admin-salary |
Расчёт зарплат администраторов |
| Штрафы | /manager/fines |
Управление штрафами |
| Создать / удалить админа | /manager/create-admin, /manager/delete-admin |
Управление пользователями |
| Раздел | URL | Описание |
|---|---|---|
| Главная | /admin |
Закрытие смены, статистика, штрафы, история своих закрытых смен |
| Мои смены | /admin/my-shifts |
Расписание от руководителя (planned_shifts), календарь; фильтр «только свои / все админы» |
- Закрыть смену можно только если руководитель выставил её в «Календаре смен».
- Дата и тип (день/ночь) определяются автоматически по текущему времени:
- 09:00–21:00 → День, дата = сегодня
- 21:00–00:00 → Ночь, дата = сегодня (день начала ночи)
- 00:00–09:00 → Ночь, дата = вчера
- Обед (
meal_allowance) всегда 100 ₽, поле у админа скрыто. - Обязательна фотофиксация (минимум 1 фото).
- Сохраняются: выручка, наличные, инкассация, аванс, примечания, премия.
- Рейтинг «Топ» — место админа среди всех по общей выручке (RPC
get_admin_revenue_ranks).
| Выручка (₽) | Премия (₽) |
|---|---|
| 8 000 – 9 999 | 300 |
| 10 000 – 11 999 | 500 |
| 12 000 – 13 999 | 700 |
| 14 000 – 17 999 | … (см. код calculateBonus в src/app/admin/page.tsx) |
(В БД также есть bonus_config и триггеры — при расхождении сверяйте клиентский расчёт и триггеры.)
git clone https://github.com/Kalekakektop2/admin-calendar.git
cd admin-calendar
npm installСкопируйте env.example → .env.local:
NEXT_PUBLIC_SUPABASE_URL=your-project-url
NEXT_PUBLIC_SUPABASE_ANON_KEY=your-anon-keyЗначения: Supabase → Project Settings → API.
Выполните SQL-файлы из supabase/migrations/ по порядку в Supabase SQL Editor:
| Файл | Назначение |
|---|---|
001_initial_schema.sql |
users, shifts, shift_photos, RLS |
002_bonus_config.sql |
Конфиг бонусов |
003_bonus_calculation_function.sql |
Функции/триггеры бонусов |
004_fines.sql |
Штрафы |
004_fix_bonus_amount_nullable.sql |
nullable bonus |
005_encashment.sql |
Инкассация |
005_remove_revenue_constraint.sql |
Снятие ограничений выручки |
006_add_shift_type.sql |
Тип смены day/night |
006_update_bonus_config.sql |
Обновление конфига бонусов |
007_advances.sql |
Таблица advances |
007_fix_photo_policies.sql |
Политики Storage/фото |
008_add_username.sql |
username у users |
008_advance_field.sql |
Поле advance в shifts |
009_increase_decimal_limits.sql |
Увеличение DECIMAL |
009_meal_allowance.sql |
Обед |
010_update_bonus_calculation.sql |
Пересчёт бонусов |
011_planned_shifts_and_user_color.sql |
planned_shifts + users.color |
012_planned_shifts_admin_read_all.sql |
Админы видят все planned_shifts и профили |
013_admin_revenue_rank.sql |
Функция Топ по выручке |
014_planned_shifts_google_source.sql |
Google-синк: source, manual_override, planned_shift_blocks |
- Создайте таблицу с колонками: дата | админ | тип (
день/ночь). - Доступ: Все, у кого есть ссылка → Читатель.
- В
.env.local/ Vercel:GOOGLE_SCHEDULE_SHEET_ID=...и опциональноGOOGLE_SCHEDULE_SHEET_GID=0- или
GOOGLE_SCHEDULE_CSV_URL=https://docs.google.com/spreadsheets/d/.../export?format=csv&gid=0
- В «Календарь смен» нажмите «Синк с Google».
- Ручные правки руководителя (
source=manual/manual_override) не перезаписываются Google. - Если руководитель удалил смену — слот блокируется (
planned_shift_blocks), Google не вернёт её, пока руководитель не поставит снова.
Затем выполните supabase/storage_setup.sql (bucket shift-photos).
- Создайте пользователя в Supabase Auth → Users.
- Добавьте запись в
usersс тем же UUID:
INSERT INTO users (id, email, full_name, username, role, color)
VALUES (
'auth-user-id',
'admin@example.com',
'Имя Фамилия',
'admin_login',
'admin', -- или 'manager'
'#3b82f6'
);npm run dev # http://localhost:3000
npm run build
npm start
npm run lintgit add .
git commit -m "описание изменений"
git push origin mainVercel подхватывает main автоматически.
Переменные NEXT_PUBLIC_SUPABASE_* должны быть заданы в настройках проекта Vercel.
admin-calendar/
├── src/
│ ├── app/
│ │ ├── admin/
│ │ │ ├── page.tsx # Главная админа (закрытие смены, статистика, штрафы)
│ │ │ ├── my-shifts/page.tsx # Расписание (planned_shifts)
│ │ │ └── layout.tsx
│ │ ├── manager/
│ │ │ ├── page.tsx # Все смены за месяц
│ │ │ ├── shift-calendar/ # Выставление смен
│ │ │ ├── closed-shifts/ # Закрытые + фильтр админов
│ │ │ ├── monthly-reports/
│ │ │ ├── admin-salary/
│ │ │ ├── fines/
│ │ │ ├── create-admin/
│ │ │ ├── delete-admin/
│ │ │ └── layout.tsx
│ │ ├── login/ | logout/ | unauthorized/
│ │ ├── layout.tsx | page.tsx | globals.css
│ ├── components/
│ │ ├── providers/ # Supabase, тема
│ │ └── ui/ # card, modal, stat-card, file-upload, theme-toggle
│ ├── lib/
│ │ ├── auth.ts # requireRole, getUserRole, …
│ │ ├── supabase/ # client + server
│ │ └── utils.ts
│ ├── middleware.ts # Защита /admin, /manager
│ └── types/database.ts # Типы схемы
├── supabase/
│ ├── migrations/ # 001–013
│ └── storage_setup.sql
├── env.example
├── package.json
└── README.md
| Поле | Описание |
|---|---|
id |
UUID = Auth user id |
email, full_name, username |
Профиль |
role |
admin | manager |
color |
HEX-цвет в календаре (у каждого админа свой) |
| Поле | Описание |
|---|---|
user_id |
Админ |
shift_date |
Дата смены |
shift_type |
day | night |
| UNIQUE | (user_id, shift_date, shift_type) |
| Поле | Описание |
|---|---|
user_id, shift_date, shift_type |
Кто, когда, день/ночь |
total_revenue, cash_balance, card_revenue |
Финансы |
bonus_amount |
Премия |
encashment |
Инкассация |
advance |
Аванс |
meal_allowance |
Обед (фиксированно 100) |
notes |
Примечания |
Фото к смене (Storage bucket shift-photos).
Штрафы: user_id, amount, fine_date, comment.
Авансы, выдаваемые руководителем (историческая/доп. сущность; в отчёте смены используется поле shifts.advance).
Настройки расчёта бонуса на стороне БД.
get_admin_revenue_ranks()— рейтинг админов по суммеtotal_revenue(для блока Топ).
- Таблицы с Row Level Security.
- Руководитель: полный доступ к сменам, планам, штрафам, пользователям.
- Администратор:
- свои закрытые смены (create/update/select own);
- просмотр всех
planned_shifts(расписание коллег) — миграция012; - просмотр профилей коллег (имена/цвета);
- рейтинг через SECURITY DEFINER-функцию
013.
- Маршруты
/adminи/managerзащищеныmiddleware+ проверкой роли в layout.
DELETE FROM shift_photos;
DELETE FROM shifts;DELETE FROM shift_photos;
DELETE FROM shifts;
DELETE FROM planned_shifts;SELECT COUNT(*) FROM shifts;
SELECT COUNT(*) FROM planned_shifts;npm run dev
npm run build
npm run lint
git add .
git commit -m "feat: ..."
git push origin main # → Vercel deployНе коммитить .env.local и секреты.
Изменения схемы — только новыми миграциями в supabase/migrations/, с обновлением src/types/database.ts при необходимости.
| Проблема | Что проверить |
|---|---|
| Не логинится | .env.local / env на Vercel, Auth user + запись в users |
| «Нет запланированной смены» | Есть ли запись в planned_shifts на дату/тип; миграция 011 |
| «Мои смены» пустые у коллег | Миграция 012 (RLS SELECT) |
| Топ показывает «—» | Миграция 013, функция get_admin_revenue_ranks |
| Аванс всегда 0 | Колонка advance (008_advance_field.sql); повторно закрыть смену после фикса |
| Фото не грузятся | storage_setup.sql, bucket shift-photos, политики Storage |
| Ошибка policy already exists | В SQL: DROP POLICY IF EXISTS "..." ON table; перед CREATE POLICY |
Внутреннее использование компьютерным клубом.
Обратная связь и предложения по улучшению приветствуются.