Guide Manager Admin — web-админка для управления гидами, компаниями, экскурсиями и заявками в системе Guide Manager.
Проект является частью full-product связки:
- Flutter client → Guide Manager
- Admin panel → Guide Manager Admin
- Backend → Firebase Authentication + Cloud Firestore
Админка работает без отдельного production backend. Все данные хранятся в Firebase, а доступ контролируется через Firebase Auth, custom claims и Firestore Security Rules.
- вход через Firebase Authentication
- проверка admin-доступа через custom claim
admin: true - защищенные маршруты
- отдельное состояние для пользователей без прав администратора
- просмотр списка гидов
- поиск по имени и email
- просмотр профиля гида
- редактирование данных
- одобрение зарегистрированных гидов
- назначение уровня доступа
Уровни гидов: trainee, junior, middle, senior
- создание и редактирование компаний
- хранение контактной информации
- удаление компаний
- управление blacklist
Blacklist используется, чтобы ограничивать доступ отдельных гидов к экскурсиям конкретной компании.
- календарь экскурсий
- создание и редактирование экскурсии
- настройка даты, времени, маршрута и места встречи
- выбор компании
- указание требуемого количества гидов
- настройка подходящих уровней гидов
- автоматический расчет свободных мест
- удаление экскурсии вместе с заявками
- просмотр заявок от гидов
- фильтрация по статусу
- принятие заявки
- отклонение заявки
- добавление комментария к решению
- транзакционное обновление заявки и экскурсии
Статусы заявок: pending, accepted, rejected
При принятии заявки система проверяет, что гид подходит по уровню, не находится в blacklist компании, еще не назначен на экскурсию, а на экскурсии есть свободные места.
React
TypeScript
Vite
Firebase Authentication
Cloud Firestore
Firebase Hosting
React Router
TanStack Query
React Hook Form
Zod
date-fns
lucide-reactПроект использует feature/entity-first структуру:
src/
app/
App.tsx
router.tsx
styles.css
entities/
application/
company/
excursion/
guide/
features/
auth/
firebase/
auth.ts
client.ts
firestore.ts
pages/
ApplicationsPage.tsx
CompaniesPage.tsx
DashboardPage.tsx
ExcursionsPage.tsx
GuidesPage.tsx
LoginPage.tsx
shared/
constants/
lib/
ui/Основные коллекции Firestore:
guides/{uid}Профиль гида.
uid документа совпадает с Firebase Auth UID пользователя. После регистрации гид создается как не одобренный пользователь с isApproved: false.
companies/{companyId}Компании-заказчики экскурсий. В документе компании также хранится blacklist email-ов гидов.
excursions/{excursionId}Экскурсии с датой, маршрутом, компанией, требуемым количеством гидов, подходящими уровнями и списком назначенных гидов.
excursions/{excursionId}/applications/{guideUid}Заявки гидов на экскурсии. ID заявки совпадает с UID гида, поэтому один гид может создать только одну заявку на конкретную экскурсию.
Доступ к данным контролируется через Firestore Security Rules.
Основная модель доступа:
- админ определяется через Firebase custom claim
admin: true - гид получает доступ только после одобрения администратором
- гид может читать только доступные ему, назначенные ему или связанные с его заявками экскурсии
- гид может создать только свою заявку
- заявка создается только если гид подходит по уровню и не находится в blacklist компании
- принятие заявки выполняется через transaction
- при принятии заявки проверяются свободные места, уровень гида и blacklist
Firestore rules находятся в файле firestore.rules
Создайте .env.local на основе .env.example:
cp .env.example .env.localПример переменных:
VITE_FIREBASE_API_KEY=
VITE_FIREBASE_AUTH_DOMAIN=
VITE_FIREBASE_PROJECT_ID=
VITE_FIREBASE_STORAGE_BUCKET=
VITE_FIREBASE_MESSAGING_SENDER_ID=
VITE_FIREBASE_APP_ID=Во frontend env нельзя добавлять приватные ключи:
SERVICE_ACCOUNT
PRIVATE_KEY
FIREBASE_CREDENTIALS
GOOGLE_APPLICATION_CREDENTIALSService account используется только локально для служебных scripts.
npm installFirebase config можно найти в Firebase Console:
Project settings → General → Your apps → Web appnpm run devnpm run typecheck
npm run buildПосле успешной сборки Vite создаст папку:
dist/Админка доступна только пользователям с custom claim:
admin: trueДля назначения первого администратора используется локальный script через Firebase Admin SDK.
export GOOGLE_APPLICATION_CREDENTIALS=/absolute/path/service-account.json
npm run admin:set -- admin@email.comFIREBASE_CREDENTIALS=/absolute/path/service-account.json \
npm run admin:set -- admin@email.comПосле назначения claim пользователь должен выйти из аккаунта и войти снова, чтобы получить новый ID token.
Админка деплоится на Firebase Hosting как статическое Vite-приложение.
npx firebase-tools projects:list
npx firebase-tools usenpm run buildnpx firebase-tools deploy --only hosting:adminProduction URL:
https://traveltech-admin.web.appFlutter-клиент для гидов:
https://github.com/wyroxx/guide-managerКлиент используется гидами для:
- регистрации;
- ожидания одобрения администратора;
- просмотра доступных экскурсий;
- подачи заявок;
- отслеживания статуса заявок;
- просмотра назначенных экскурсий в календаре.
1. Гид регистрируется во Flutter-приложении.
2. В Firestore создается guides/{uid} с isApproved: false.
3. Админ открывает Guide Manager Admin.
4. Админ видит нового гида.
5. Админ назначает уровень и одобряет гида.
6. Гид получает доступ к подходящим экскурсиям.
7. Админ создает компанию.
8. Админ создает экскурсию.
9. Гид подает заявку на экскурсию.
10. Админ принимает или отклоняет заявку.
11. Flutter-клиент показывает гиду актуальный статус.




