@mashka818/exam-de-template 1.0.1 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (140) hide show
  1. package/exam-guides/commented-code/client/index.html +7 -0
  2. package/exam-guides/commented-code/client/package-lock.json +541 -6
  3. package/exam-guides/commented-code/client/package.json +1 -0
  4. package/exam-guides/commented-code/client/public/images/README.txt +4 -24
  5. package/exam-guides/commented-code/client/public/images/about-cleaning.png +0 -0
  6. package/exam-guides/commented-code/client/public/images/admin-banner.png +0 -0
  7. package/exam-guides/commented-code/client/public/images/empty-requests.png +0 -0
  8. package/exam-guides/commented-code/client/public/images/footer-photo-1.png +0 -0
  9. package/exam-guides/commented-code/client/public/images/footer-photo-2.png +0 -0
  10. package/exam-guides/commented-code/client/public/images/footer-photo-3.png +0 -0
  11. package/exam-guides/commented-code/client/public/images/home-hero.png +0 -0
  12. package/exam-guides/commented-code/client/public/images/login-banner.png +0 -0
  13. package/exam-guides/commented-code/client/public/images/logo.png +0 -0
  14. package/exam-guides/commented-code/client/public/images/new-request-banner.png +0 -0
  15. package/exam-guides/commented-code/client/public/images/register-banner.png +0 -0
  16. package/exam-guides/commented-code/client/public/images/requests-banner.png +0 -0
  17. package/exam-guides/commented-code/client/public/images/slide-1.png +0 -0
  18. package/exam-guides/commented-code/client/public/images/slide-2.png +0 -0
  19. package/exam-guides/commented-code/client/public/images/slide-3.png +0 -0
  20. package/exam-guides/commented-code/client/src/App.jsx +14 -0
  21. package/exam-guides/commented-code/client/src/api.js +16 -2
  22. package/exam-guides/commented-code/client/src/components/FormField.jsx +7 -0
  23. package/exam-guides/commented-code/client/src/components/Layout.jsx +8 -0
  24. package/exam-guides/commented-code/client/src/components/PageImage.jsx +7 -0
  25. package/exam-guides/commented-code/client/src/components/ProtectedRoute.jsx +7 -0
  26. package/exam-guides/commented-code/client/src/components/UserNav.jsx +7 -0
  27. package/exam-guides/commented-code/client/src/components/landing/HeroSlider.jsx +7 -0
  28. package/exam-guides/commented-code/client/src/components/landing/LandingLayout.jsx +7 -0
  29. package/exam-guides/commented-code/client/src/components/landing/SiteFooter.jsx +7 -0
  30. package/exam-guides/commented-code/client/src/config/images.js +26 -28
  31. package/exam-guides/commented-code/client/src/constants/services.js +7 -0
  32. package/exam-guides/commented-code/client/src/context/AuthContext.jsx +8 -0
  33. package/exam-guides/commented-code/client/src/index.css +8 -0
  34. package/exam-guides/commented-code/client/src/main.jsx +8 -0
  35. package/exam-guides/commented-code/client/src/pages/AdminPage.jsx +59 -24
  36. package/exam-guides/commented-code/client/src/pages/LandingPage.jsx +7 -0
  37. package/exam-guides/commented-code/client/src/pages/LoginPage.jsx +8 -0
  38. package/exam-guides/commented-code/client/src/pages/RegisterPage.jsx +8 -0
  39. package/exam-guides/commented-code/client/src/pages/RequestFormPage.jsx +7 -0
  40. package/exam-guides/commented-code/client/src/pages/RequestsPage.jsx +7 -0
  41. package/exam-guides/commented-code/client/src/utils/validation.js +8 -0
  42. package/exam-guides/commented-code/client/vite.config.js +7 -0
  43. package/exam-guides/commented-code/server/db/init.js +7 -0
  44. package/exam-guides/commented-code/server/db/pool.js +7 -0
  45. package/exam-guides/commented-code/server/db/schema.sql +5 -0
  46. package/exam-guides/commented-code/server/db/seed.sql +5 -0
  47. package/exam-guides/commented-code/server/index.js +7 -0
  48. package/exam-guides/commented-code/server/middleware/auth.js +7 -0
  49. package/exam-guides/commented-code/server/routes/admin.js +23 -3
  50. package/exam-guides/commented-code/server/routes/auth.js +7 -0
  51. package/exam-guides/commented-code/server/routes/requests.js +7 -0
  52. package/exam-guides/commented-code/server/routes/services.js +7 -0
  53. package/exam-guides/commented-code/server/utils/validation.js +7 -0
  54. package/exam-project/EXAM_COMMANDS.txt +47 -0
  55. package/exam-project/README.md +4 -7
  56. package/exam-project/THEME_BANQUETAM_NET.md +106 -0
  57. package/exam-project/client/index.html +7 -0
  58. package/exam-project/client/package-lock.json +541 -6
  59. package/exam-project/client/package.json +1 -0
  60. package/exam-project/client/public/images/README.txt +4 -24
  61. package/exam-project/client/public/images/about-cleaning.png +0 -0
  62. package/exam-project/client/public/images/admin-banner.png +0 -0
  63. package/exam-project/client/public/images/empty-requests.png +0 -0
  64. package/exam-project/client/public/images/footer-photo-1.png +0 -0
  65. package/exam-project/client/public/images/footer-photo-2.png +0 -0
  66. package/exam-project/client/public/images/footer-photo-3.png +0 -0
  67. package/exam-project/client/public/images/home-hero.png +0 -0
  68. package/exam-project/client/public/images/login-banner.png +0 -0
  69. package/exam-project/client/public/images/logo.png +0 -0
  70. package/exam-project/client/public/images/new-request-banner.png +0 -0
  71. package/exam-project/client/public/images/register-banner.png +0 -0
  72. package/exam-project/client/public/images/requests-banner.png +0 -0
  73. package/exam-project/client/public/images/slide-1.png +0 -0
  74. package/exam-project/client/public/images/slide-2.png +0 -0
  75. package/exam-project/client/public/images/slide-3.png +0 -0
  76. package/exam-project/client/src/App.jsx +35 -1
  77. package/exam-project/client/src/api.js +37 -2
  78. package/exam-project/client/src/components/FormField.jsx +22 -1
  79. package/exam-project/client/src/components/Layout.jsx +34 -4
  80. package/exam-project/client/src/components/PageImage.jsx +24 -1
  81. package/exam-project/client/src/components/ProtectedRoute.jsx +23 -1
  82. package/exam-project/client/src/components/UserNav.jsx +20 -0
  83. package/exam-project/client/src/components/landing/HeroSlider.jsx +23 -2
  84. package/exam-project/client/src/components/landing/LandingLayout.jsx +23 -1
  85. package/exam-project/client/src/components/landing/SiteFooter.jsx +20 -0
  86. package/exam-project/client/src/config/images.js +45 -26
  87. package/exam-project/client/src/constants/services.js +20 -1
  88. package/exam-project/client/src/context/AuthContext.jsx +26 -1
  89. package/exam-project/client/src/index.css +28 -1
  90. package/exam-project/client/src/main.jsx +20 -1
  91. package/exam-project/client/src/pages/AdminPage.jsx +65 -7
  92. package/exam-project/client/src/pages/LandingPage.jsx +23 -0
  93. package/exam-project/client/src/pages/LoginPage.jsx +28 -2
  94. package/exam-project/client/src/pages/RegisterPage.jsx +29 -1
  95. package/exam-project/client/src/pages/RequestFormPage.jsx +28 -3
  96. package/exam-project/client/src/pages/RequestsPage.jsx +26 -1
  97. package/exam-project/client/src/utils/validation.js +26 -1
  98. package/exam-project/client/vite.config.js +22 -1
  99. package/exam-project/server/db/init.js +27 -3
  100. package/exam-project/server/db/pool.js +20 -1
  101. package/exam-project/server/db/schema.sql +17 -0
  102. package/exam-project/server/db/seed.sql +8 -0
  103. package/exam-project/server/index.js +24 -1
  104. package/exam-project/server/middleware/auth.js +22 -1
  105. package/exam-project/server/routes/admin.js +44 -4
  106. package/exam-project/server/routes/auth.js +27 -1
  107. package/exam-project/server/routes/requests.js +27 -4
  108. package/exam-project/server/routes/services.js +21 -1
  109. package/exam-project/server/utils/validation.js +27 -2
  110. package/package.json +1 -1
  111. package/exam-guides/commented-code/client/public/images/about-cleaning.svg +0 -4
  112. package/exam-guides/commented-code/client/public/images/admin-banner.svg +0 -1
  113. package/exam-guides/commented-code/client/public/images/empty-requests.svg +0 -1
  114. package/exam-guides/commented-code/client/public/images/footer-photo-1.svg +0 -4
  115. package/exam-guides/commented-code/client/public/images/footer-photo-2.svg +0 -4
  116. package/exam-guides/commented-code/client/public/images/footer-photo-3.svg +0 -4
  117. package/exam-guides/commented-code/client/public/images/home-hero.svg +0 -4
  118. package/exam-guides/commented-code/client/public/images/login-banner.svg +0 -1
  119. package/exam-guides/commented-code/client/public/images/logo.svg +0 -4
  120. package/exam-guides/commented-code/client/public/images/new-request-banner.svg +0 -1
  121. package/exam-guides/commented-code/client/public/images/register-banner.svg +0 -1
  122. package/exam-guides/commented-code/client/public/images/requests-banner.svg +0 -1
  123. package/exam-guides/commented-code/client/public/images/slide-1.svg +0 -6
  124. package/exam-guides/commented-code/client/public/images/slide-2.svg +0 -5
  125. package/exam-guides/commented-code/client/public/images/slide-3.svg +0 -5
  126. package/exam-project/client/public/images/about-cleaning.svg +0 -4
  127. package/exam-project/client/public/images/admin-banner.svg +0 -1
  128. package/exam-project/client/public/images/empty-requests.svg +0 -1
  129. package/exam-project/client/public/images/footer-photo-1.svg +0 -4
  130. package/exam-project/client/public/images/footer-photo-2.svg +0 -4
  131. package/exam-project/client/public/images/footer-photo-3.svg +0 -4
  132. package/exam-project/client/public/images/home-hero.svg +0 -4
  133. package/exam-project/client/public/images/login-banner.svg +0 -1
  134. package/exam-project/client/public/images/logo.svg +0 -4
  135. package/exam-project/client/public/images/new-request-banner.svg +0 -1
  136. package/exam-project/client/public/images/register-banner.svg +0 -1
  137. package/exam-project/client/public/images/requests-banner.svg +0 -1
  138. package/exam-project/client/public/images/slide-1.svg +0 -6
  139. package/exam-project/client/public/images/slide-2.svg +0 -5
  140. package/exam-project/client/public/images/slide-3.svg +0 -5
@@ -1,3 +1,17 @@
1
+ /**
2
+ * =============================================================================
3
+ * ФАЙЛ: client/src/App.jsx
4
+ * МАРШРУТЫ (react-router). Пункты ДЭ = пути ниже.
5
+ * / → pages/LandingPage.jsx
6
+ * /register → RegisterPage.jsx (п.1)
7
+ * /login → LoginPage.jsx (п.2)
8
+ * /requests → RequestsPage.jsx (п.3)
9
+ * /requests/form → RequestFormPage.jsx (п.4)
10
+ * /admin → AdminPage.jsx (п.5)
11
+ * Новая страница: import + <Route path="..." element={...} />
12
+ * =============================================================================
13
+ */
14
+
1
15
  /**
2
16
  * =============================================================================
3
17
  * App.jsx — МАРШРУТЫ REACT (react-router-dom)
@@ -1,3 +1,12 @@
1
+ /**
2
+ * =============================================================================
3
+ * ФАЙЛ: client/src/api.js
4
+ * ВСЕ запросы к бэкенду. Прокси: client/vite.config.js → localhost:3001
5
+ * Добавить метод: 1) server/routes/... 2) строка в export const api 3) вызов на странице
6
+ * Ошибки формы: catch (e) → e.data.errors
7
+ * =============================================================================
8
+ */
9
+
1
10
  /**
2
11
  * =============================================================================
3
12
  * HTTP-ЗАПРОСЫ К API (все вызовы бэкенда в одном файле)
@@ -64,8 +73,13 @@ export const api = {
64
73
  // БАНКЕТАМ.НЕТ: postReview: (id, body) => request(`/requests/${id}/review`, { method: 'POST', body: JSON.stringify(body) }),
65
74
 
66
75
  // --- Админ → server/routes/admin.js (п.5) ---
67
- // БАНКЕТАМ.НЕТ: adminGetRequests: (params) => request(`/admin/requests?status=${params.status}`)
68
- adminGetRequests: () => request('/admin/requests'),
76
+ // params.status: 'all' | 'new' | 'in_progress' | 'completed' | 'cancelled'
77
+ adminGetRequests: (params = {}) => {
78
+ const q = new URLSearchParams();
79
+ if (params.status && params.status !== 'all') q.set('status', params.status);
80
+ const qs = q.toString();
81
+ return request(`/admin/requests${qs ? `?${qs}` : ''}`);
82
+ },
69
83
  adminUpdateStatus: (id, body) =>
70
84
  request(`/admin/requests/${id}/status`, { method: 'PATCH', body: JSON.stringify(body) }),
71
85
  };
@@ -1,3 +1,10 @@
1
+ /**
2
+ * =============================================================================
3
+ * ФАЙЛ: client/src/components/FormField.jsx
4
+ * Обёртка label+input+ошибка. Менять label на страницах, не здесь.
5
+ * =============================================================================
6
+ */
7
+
1
8
  /**
2
9
  * =============================================================================
3
10
  * FormField.jsx — ПОЛЕ ФОРМЫ (label + input + ошибка)
@@ -1,3 +1,11 @@
1
+ /**
2
+ * =============================================================================
3
+ * ФАЙЛ: client/src/components/Layout.jsx
4
+ * Шапка всех страниц кроме лендинга. Менять: brandName, brandTagline, headerStyles, logo в images.js
5
+ * variant со страницы: register | login | dashboard | admin
6
+ * =============================================================================
7
+ */
8
+
1
9
  /**
2
10
  * =============================================================================
3
11
  * LAYOUT — общая обёртка всех страниц (шапка + контент)
@@ -1,3 +1,10 @@
1
+ /**
2
+ * =============================================================================
3
+ * ФАЙЛ: client/src/components/PageImage.jsx
4
+ * Картинки: <PageImage imageKey="logo" />. Ключи в config/images.js
5
+ * =============================================================================
6
+ */
7
+
1
8
  /**
2
9
  * =============================================================================
3
10
  * PageImage.jsx — КАРТИНКА НА СТРАНИЦЕ (единый способ)
@@ -1,3 +1,10 @@
1
+ /**
2
+ * =============================================================================
3
+ * ФАЙЛ: client/src/components/ProtectedRoute.jsx
4
+ * Защита маршрутов. role="user" | "admin". Без входа → /login
5
+ * =============================================================================
6
+ */
7
+
1
8
  /**
2
9
  * =============================================================================
3
10
  * ЗАЩИТА МАРШРУТОВ — только для авторизованных
@@ -1,3 +1,10 @@
1
+ /**
2
+ * =============================================================================
3
+ * ФАЙЛ: client/src/components/UserNav.jsx
4
+ * Вкладки в шапке заказчика: /requests и /requests/form. Менять подписи ссылок.
5
+ * =============================================================================
6
+ */
7
+
1
8
  /**
2
9
  * =============================================================================
3
10
  * UserNav.jsx — ВКЛАДКИ В ШАПКЕ (только заказчик, variant="dashboard")
@@ -1,3 +1,10 @@
1
+ /**
2
+ * =============================================================================
3
+ * ФАЙЛ: client/src/components/landing/HeroSlider.jsx
4
+ * Слайдер лендинга. SLIDE_KEYS + slideText + PNG slide-1… в images.js. Интервал setInterval (Банкетам: 3000, 4 слайда).
5
+ * =============================================================================
6
+ */
7
+
1
8
  /**
2
9
  * =============================================================================
3
10
  * HeroSlider.jsx — СЛАЙДЕР НА ЛЕНДИНГЕ (модуль 2 / М2)
@@ -1,3 +1,10 @@
1
+ /**
2
+ * =============================================================================
3
+ * ФАЙЛ: client/src/components/landing/LandingLayout.jsx
4
+ * Шапка лендинга /. brandName, ссылки Вход/Регистрация.
5
+ * =============================================================================
6
+ */
7
+
1
8
  /**
2
9
  * =============================================================================
3
10
  * LandingLayout.jsx — ШАПКА ЛЕНДИНГА (без Layout.jsx)
@@ -1,3 +1,10 @@
1
+ /**
2
+ * =============================================================================
3
+ * ФАЙЛ: client/src/components/landing/SiteFooter.jsx
4
+ * Подвал лендинга. footerPhoto1-3 в images.js. Тексты компании.
5
+ * =============================================================================
6
+ */
7
+
1
8
  /**
2
9
  * =============================================================================
3
10
  * SiteFooter.jsx — ПОДВАЛ ЛЕНДИНГА
@@ -1,3 +1,11 @@
1
+ /**
2
+ * =============================================================================
3
+ * ФАЙЛ: client/src/config/images.js
4
+ * КАРТИНКИ: только менять file и alt. Файлы PNG лежат в client/public/images/
5
+ * На экзамене: экспорт Figma → тот же файл (logo.png, slide-1.png…). Пути в коде не пишем — PageImage imageKey
6
+ * =============================================================================
7
+ */
8
+
1
9
  /**
2
10
  * =============================================================================
3
11
  * КОНФИГУРАЦИЯ ИЗОБРАЖЕНИЙ
@@ -6,8 +14,8 @@
6
14
  * В коде подключаются через URL: /images/имя-файла
7
15
  *
8
16
  * НА ЭКЗАМЕНЕ:
9
- * 1) Экспорт из Figma → PNG в public/images/
10
- * 2) Если имя файла другоепоменяйте только этот файл
17
+ * 1) Экспорт из Figma → PNG в public/images/ (только PNG, не SVG)
18
+ * 2) Имя файла как ниже (logo.png, slide-1.png…) замените файл, config не трогайте
11
19
  * 3) alt — для доступности; замените текст под новую тему
12
20
  * БАНКЕТАМ.НЕТ: slide4; alt про банкеты/залы; logo «Банкетам.Нет»
13
21
  *
@@ -31,64 +39,54 @@ export const IMAGES_BASE = '/images';
31
39
  export const IMAGES = {
32
40
  // Шапка на всех страницах → логотип компании / портала
33
41
  logo: {
34
- file: 'logo.svg', // ЗАМЕНИТЕ на logo.png после экспорта из Figma
35
- alt: 'Логотип «Мой Не Сам»', // → название вашей организации
42
+ file: 'logo.png',
43
+ alt: 'Логотип «Мой Не Сам»',
36
44
  },
37
45
 
38
- // Главная (/) — иллюстрация услуги
39
46
  homeHero: {
40
- file: 'home-hero.svg',
47
+ file: 'home-hero.png',
41
48
  alt: 'Клининговые услуги на дому',
42
49
  },
43
50
 
44
- // Регистрация (/register)
45
51
  registerBanner: {
46
- file: 'register-banner.svg',
52
+ file: 'register-banner.png',
47
53
  alt: 'Регистрация нового заказчика',
48
54
  },
49
55
 
50
- // Вход (/login)
51
56
  loginBanner: {
52
- file: 'login-banner.svg',
57
+ file: 'login-banner.png',
53
58
  alt: 'Вход в личный кабинет',
54
59
  },
55
60
 
56
- // Список заявок (/requests)
57
61
  requestsBanner: {
58
- file: 'requests-banner.svg',
62
+ file: 'requests-banner.png',
59
63
  alt: 'История заявок на уборку',
60
64
  },
61
65
 
62
- // Новая заявка (/requests/new)
63
66
  newRequestBanner: {
64
- file: 'new-request-banner.svg',
67
+ file: 'new-request-banner.png',
65
68
  alt: 'Оформление заявки на услугу',
66
69
  },
67
70
 
68
- // Админ-панель (/admin)
69
71
  adminBanner: {
70
- file: 'admin-banner.svg',
72
+ file: 'admin-banner.png',
71
73
  alt: 'Панель администратора',
72
74
  },
73
75
 
74
- // Пустой список заявок
75
76
  emptyRequests: {
76
- file: 'empty-requests.svg',
77
+ file: 'empty-requests.png',
77
78
  alt: 'Заявок пока нет',
78
79
  },
79
80
 
80
- // --- Лендинг: слайдер (HeroSlider.jsx) ---
81
- slide1: { file: 'slide-1.svg', alt: 'Общий клининг' },
82
- slide2: { file: 'slide-2.svg', alt: 'Генеральная уборка' },
83
- slide3: { file: 'slide-3.svg', alt: 'Химчистка ковров и мебели' },
81
+ slide1: { file: 'slide-1.png', alt: 'Общий клининг' },
82
+ slide2: { file: 'slide-2.png', alt: 'Генеральная уборка' },
83
+ slide3: { file: 'slide-3.png', alt: 'Химчистка ковров и мебели' },
84
84
 
85
- // Лендинг: блок «О клининге»
86
- aboutCleaning: { file: 'about-cleaning.svg', alt: 'Профессиональный клининг' },
85
+ aboutCleaning: { file: 'about-cleaning.png', alt: 'Профессиональный клининг' },
87
86
 
88
- // Лендинг: футер 3 фото (команда / офис / работы)
89
- footerPhoto1: { file: 'footer-photo-1.svg', alt: 'Сотрудник 1' },
90
- footerPhoto2: { file: 'footer-photo-2.svg', alt: 'Сотрудник 2' },
91
- footerPhoto3: { file: 'footer-photo-3.svg', alt: 'Сотрудник 3' },
87
+ footerPhoto1: { file: 'footer-photo-1.png', alt: 'Сотрудник 1' },
88
+ footerPhoto2: { file: 'footer-photo-2.png', alt: 'Сотрудник 2' },
89
+ footerPhoto3: { file: 'footer-photo-3.png', alt: 'Сотрудник 3' },
92
90
  };
93
91
 
94
92
  /** Собрать полный URL для тега <img src="..."> */
@@ -1,3 +1,10 @@
1
+ /**
2
+ * =============================================================================
3
+ * ФАЙЛ: client/src/constants/services.js
4
+ * Подписи услуг на лендинге. Синхронизировать с server/db/seed.sql
5
+ * =============================================================================
6
+ */
7
+
1
8
  /**
2
9
  * =============================================================================
3
10
  * constants/services.js — НАЗВАНИЯ УСЛУГ НА ЛЕНДИНГЕ (только отображение)
@@ -1,3 +1,11 @@
1
+ /**
2
+ * =============================================================================
3
+ * ФАЙЛ: client/src/context/AuthContext.jsx
4
+ * login / register / logout / user. JWT в localStorage (api.js TOKEN_KEY).
5
+ * После входа: user.role → 'user' | 'admin'
6
+ * =============================================================================
7
+ */
8
+
1
9
  /**
2
10
  * =============================================================================
3
11
  * КОНТЕКСТ АВТОРИЗАЦИИ — user, login, register, logout
@@ -1,3 +1,11 @@
1
+ /**
2
+ * =============================================================================
3
+ * ФАЙЛ: client/src/index.css
4
+ * Цвета бренда: @theme --color-brand. Анимации: animate-fade-up, animate-slide-in.
5
+ * Ошибки полей: .field-error, .input-error на input
6
+ * =============================================================================
7
+ */
8
+
1
9
  @import 'tailwindcss';
2
10
 
3
11
  /**
@@ -1,3 +1,11 @@
1
+ /**
2
+ * =============================================================================
3
+ * ФАЙЛ: client/src/main.jsx
4
+ * ТОЧКА ВХОДА React. Обычно НЕ МЕНЯЮТ.
5
+ * Цепочка: index.html #root → main.jsx → AuthProvider → App.jsx
6
+ * =============================================================================
7
+ */
8
+
1
9
  /**
2
10
  * =============================================================================
3
11
  * main.jsx — ТОЧКА ВХОДА REACT (запуск приложения в браузере)
@@ -1,50 +1,56 @@
1
+ /**
2
+ * =============================================================================
3
+ * ФАЙЛ: client/src/pages/AdminPage.jsx | URL: /admin | п.5
4
+ * Фильтр filterStatus → api.adminGetRequests({ status }). Кнопки статусов → PATCH.
5
+ * Сервер: server/routes/admin.js
6
+ * =============================================================================
7
+ */
8
+
1
9
  /**
2
10
  * =============================================================================
3
11
  * АДМИН-ПАНЕЛЬ (/admin) — п.5 задания ДЭ
4
12
  * =============================================================================
5
- * ЗАМЕНИТЕ:
6
- * логин/пароль админа server/db/init.js (seedAdmin)
7
- * кнопки статусов должны совпадать с CHECK в schema.sql
8
- * API PATCH /api/admin/requests/:id/status
9
- * картинку — admin-banner
10
- * Отличительная черта: фиолетовая шапка (variant="admin")
11
- * БАНКЕТАМ.НЕТ (п.5): кнопки только «Банкет назначен» / «Банкет завершен»; без «Отменить».
12
- * БАНКЕТАМ.НЕТ (М2): useState filterStatus, sortBy, page — select + table + «Страница 1 из N».
13
- * БАНКЕТАМ.НЕТ: toast/alert при успешной смене статуса (message уже есть).
14
- *
15
- * load(): adminGetRequests() — таблица всех заявок
16
- * updateStatus(id, status): PATCH /api/admin/requests/:id/status
17
- * cancelled + cancelReason — для клининга; БАНКЕТАМ.НЕТ убрать кнопку «Отменить»
13
+ * ФИЛЬТР ПО СТАТУСУ:
14
+ * filterStatusзначение select (all / new / in_progress / completed / cancelled)
15
+ * load() api.adminGetRequests({ status }) GET /api/admin/requests?status=...
16
+ * На сервере: server/routes/admin.js — WHERE r.status = $1
18
17
  *
19
- * ФИЛЬТР/СОРТ/СТРАНИЦЫ (М2): готовый пример кода GUIDE_PAGES.md §8.4
20
- * filterStatus state query ?status= на сервере admin.js WHERE
21
- *
22
- * GUIDE_PAGES.md §2.5 | server/routes/admin.js
18
+ * ЗАМЕНИТЕ: кнопки статусов, admin-banner, логин админа в server/db/init.js
19
+ * БАНКЕТАМ.НЕТ: подписи опций фильтра и кнопок «Банкет назначен» и т.д.
23
20
  * =============================================================================
24
21
  */
25
- import { useEffect, useState } from 'react';
22
+ import { useCallback, useEffect, useState } from 'react';
26
23
  import Layout from '../components/Layout.jsx';
27
24
  import PageImage from '../components/PageImage.jsx';
28
25
  import { api } from '../api.js';
29
26
 
27
+ const STATUS_FILTER_OPTIONS = [
28
+ { value: 'all', label: 'Все заявки' },
29
+ { value: 'new', label: 'Новая' },
30
+ { value: 'in_progress', label: 'В работе' },
31
+ { value: 'completed', label: 'Выполнено' },
32
+ { value: 'cancelled', label: 'Отменено' },
33
+ ];
34
+
30
35
  export default function AdminPage() {
31
36
  const [requests, setRequests] = useState([]);
32
37
  const [loading, setLoading] = useState(true);
38
+ const [filterStatus, setFilterStatus] = useState('all');
33
39
  const [cancelReasons, setCancelReasons] = useState({});
34
40
  const [message, setMessage] = useState('');
35
41
 
36
- const load = () => {
42
+ const load = useCallback(() => {
37
43
  setLoading(true);
38
44
  api
39
- .adminGetRequests()
45
+ .adminGetRequests({ status: filterStatus })
40
46
  .then(setRequests)
41
47
  .catch((e) => setMessage(e.message))
42
48
  .finally(() => setLoading(false));
43
- };
49
+ }, [filterStatus]);
44
50
 
45
51
  useEffect(() => {
46
52
  load();
47
- }, []);
53
+ }, [load]);
48
54
 
49
55
  const updateStatus = async (id, status) => {
50
56
  setMessage('');
@@ -55,6 +61,7 @@ export default function AdminPage() {
55
61
  }
56
62
  try {
57
63
  await api.adminUpdateStatus(id, { status, cancelReason });
64
+ setMessage('Статус обновлён');
58
65
  load();
59
66
  } catch (e) {
60
67
  setMessage(e.data?.message || e.message);
@@ -66,10 +73,39 @@ export default function AdminPage() {
66
73
  <div className="animate-fade-up">
67
74
  <PageImage imageKey="adminBanner" className="w-full h-20 object-cover rounded-xl mb-4" />
68
75
 
69
- {/* БАНКЕТАМ.НЕТ: фильтр/сортировка/пагинация — см. комментарий в шапке файла */}
70
76
  <h2 className="text-xl font-bold text-white mb-4">Панель администратора</h2>
77
+
78
+ {/* Фильтр: меняйте label в STATUS_FILTER_OPTIONS; value = status в БД */}
79
+ <div className="mb-4 flex flex-wrap items-center gap-2">
80
+ <label htmlFor="admin-filter-status" className="text-white/90 text-sm">
81
+ Статус:
82
+ </label>
83
+ <select
84
+ id="admin-filter-status"
85
+ value={filterStatus}
86
+ onChange={(e) => setFilterStatus(e.target.value)}
87
+ className="rounded-lg border border-violet-200 px-3 py-1.5 text-sm text-slate-800 bg-white"
88
+ >
89
+ {STATUS_FILTER_OPTIONS.map((opt) => (
90
+ <option key={opt.value} value={opt.value}>
91
+ {opt.label}
92
+ </option>
93
+ ))}
94
+ </select>
95
+ <button
96
+ type="button"
97
+ onClick={load}
98
+ className="text-xs px-2 py-1.5 rounded-lg bg-white/20 text-white hover:bg-white/30"
99
+ >
100
+ Обновить
101
+ </button>
102
+ </div>
103
+
71
104
  {message && <p className="text-amber-200 text-sm mb-3">{message}</p>}
72
105
  {loading && <p className="text-white/70">Загрузка…</p>}
106
+ {!loading && requests.length === 0 && (
107
+ <p className="text-white/70 text-sm">Нет заявок с выбранным статусом</p>
108
+ )}
73
109
 
74
110
  <div className="space-y-4">
75
111
  {requests.map((r) => (
@@ -98,7 +134,6 @@ export default function AdminPage() {
98
134
  {new Date(r.scheduledAt).toLocaleString('ru-RU')} · {r.paymentLabel}
99
135
  </p>
100
136
 
101
- {/* БАНКЕТАМ.НЕТ: кнопки «Банкет назначен» (in_progress) и «Банкет завершен» (completed); убрать «Отменить» */}
102
137
  <div className="mt-3 flex flex-wrap gap-2">
103
138
  {r.status === 'new' && (
104
139
  <button
@@ -1,3 +1,10 @@
1
+ /**
2
+ * =============================================================================
3
+ * ФАЙЛ: client/src/pages/LandingPage.jsx | URL: /
4
+ * Лендинг: слайдер, тексты perks, блок услуг. Не путать с Layout.jsx
5
+ * =============================================================================
6
+ */
7
+
1
8
  /**
2
9
  * =============================================================================
3
10
  * ЛЕНДИНГ (/) — главная для гостей
@@ -1,3 +1,11 @@
1
+ /**
2
+ * =============================================================================
3
+ * ФАЙЛ: client/src/pages/LoginPage.jsx | URL: /login | п.2
4
+ * login + password → AuthContext.login → admin: /admin, user: /requests
5
+ * Админ: server/db/init.js (adminka или Admin26)
6
+ * =============================================================================
7
+ */
8
+
1
9
  /**
2
10
  * =============================================================================
3
11
  * АВТОРИЗАЦИЯ (/login) — п.2 задания ДЭ
@@ -1,3 +1,11 @@
1
+ /**
2
+ * =============================================================================
3
+ * ФАЙЛ: client/src/pages/RegisterPage.jsx | URL: /register | п.1
4
+ * Поля: login, password, fullName, phone, email → POST /api/auth/register
5
+ * Менять: label, banner imageKey registerBanner, validation.js
6
+ * =============================================================================
7
+ */
8
+
1
9
  /**
2
10
  * =============================================================================
3
11
  * РЕГИСТРАЦИЯ (/register) — п.1 задания ДЭ
@@ -1,3 +1,10 @@
1
+ /**
2
+ * =============================================================================
3
+ * ФАЙЛ: client/src/pages/RequestFormPage.jsx | URL: /requests/form | п.4
4
+ * Форма заявки: api.getServices() + api.createRequest(). Поля form state → validation → POST
5
+ * =============================================================================
6
+ */
7
+
1
8
  /**
2
9
  * =============================================================================
3
10
  * п.4 ЗАДАНИЯ — «Страница формирования заявки» (/requests/form)
@@ -1,3 +1,10 @@
1
+ /**
2
+ * =============================================================================
3
+ * ФАЙЛ: client/src/pages/RequestsPage.jsx | URL: /requests | п.3
4
+ * История: api.getMyRequests(). Кнопка на /requests/form. statusLabel с сервера.
5
+ * =============================================================================
6
+ */
7
+
1
8
  /**
2
9
  * =============================================================================
3
10
  * п.3 ЗАДАНИЯ — «Страница создания заявки» (/requests)
@@ -1,3 +1,11 @@
1
+ /**
2
+ * =============================================================================
3
+ * ФАЙЛ: client/src/utils/validation.js
4
+ * Валидация форм на клиенте. ДУБЛИРОВАТЬ в server/utils/validation.js!
5
+ * register → RegisterPage | request → RequestFormPage
6
+ * =============================================================================
7
+ */
8
+
1
9
  /**
2
10
  * =============================================================================
3
11
  * ВАЛИДАЦИЯ НА КЛИЕНТЕ (мгновенные ошибки на форме)
@@ -1,3 +1,10 @@
1
+ /**
2
+ * =============================================================================
3
+ * ФАЙЛ: client/vite.config.js
4
+ * Порт 5173. proxy /api → :3001 (если сменили PORT в server/.env — поменять target)
5
+ * =============================================================================
6
+ */
7
+
1
8
  import { defineConfig } from 'vite';
2
9
  import react from '@vitejs/plugin-react';
3
10
  import tailwindcss from '@tailwindcss/vite';
@@ -1,3 +1,10 @@
1
+ /**
2
+ * =============================================================================
3
+ * ФАЙЛ: server/db/init.js
4
+ * npm run db:init — schema+seed+админ. Логин/пароль админа ЗДЕСЬ (seedAdmin).
5
+ * =============================================================================
6
+ */
7
+
1
8
  /**
2
9
  * =============================================================================
3
10
  * ИНИЦИАЛИЗАЦИЯ БД: npm run db:init
@@ -1,3 +1,10 @@
1
+ /**
2
+ * =============================================================================
3
+ * ФАЙЛ: server/db/pool.js
4
+ * Подключение БД. Только server/.env → DATABASE_URL
5
+ * =============================================================================
6
+ */
7
+
1
8
  /**
2
9
  * =============================================================================
3
10
  * pool.js — ПОДКЛЮЧЕНИЕ К PostgreSQL
@@ -1,3 +1,8 @@
1
+ -- =============================================================================
2
+ -- ФАЙЛ: server/db/schema.sql
3
+ -- Таблицы users, service_types, requests. Статусы CHECK. npm run db:init
4
+ -- =============================================================================
5
+
1
6
  -- =============================================================================
2
7
  -- СХЕМА БД — при смене темы переименуйте БД и таблицы по смыслу предметной области
3
8
  -- Тема сейчас: клининг «Мой Не Сам» → заявки на уборку (requests)
@@ -1,3 +1,8 @@
1
+ -- =============================================================================
2
+ -- ФАЙЛ: server/db/seed.sql
3
+ -- Список услуг в service_types. Менять VALUES под тему.
4
+ -- =============================================================================
5
+
1
6
  -- =============================================================================
2
7
  -- SEED — начальные записи в service_types (справочник для формы п.4)
3
8
  -- =============================================================================
@@ -1,3 +1,10 @@
1
+ /**
2
+ * =============================================================================
3
+ * ФАЙЛ: server/index.js
4
+ * Старт API :3001. Роуты /api/auth, /services, /requests, /admin
5
+ * =============================================================================
6
+ */
7
+
1
8
  /**
2
9
  * =============================================================================
3
10
  * EXPRESS — точка входа сервера
@@ -1,3 +1,10 @@
1
+ /**
2
+ * =============================================================================
3
+ * ФАЙЛ: server/middleware/auth.js
4
+ * JWT. authRequired — user routes. adminRequired — /api/admin
5
+ * =============================================================================
6
+ */
7
+
1
8
  /**
2
9
  * =============================================================================
3
10
  * JWT middleware