@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,22 +1,62 @@
1
+ /**
2
+ * =============================================================================
3
+ * ФАЙЛ: server/routes/admin.js
4
+ * GET /requests?status= — фильтр. PATCH /requests/:id/status
5
+ * =============================================================================
6
+ */
1
7
 
8
+ /**
9
+ * =============================================================================
10
+ * ADMIN — /api/admin (только role=admin, логин adminka)
11
+ * =============================================================================
12
+ * GET /requests — все заявки всех пользователей
13
+ * PATCH /requests/:id/status — in_progress | completed | cancelled + cancelReason
14
+ * БАНКЕТАМ.НЕТ (п.5): Admin26 / Demo20; ALLOWED_STATUSES = ['in_progress','completed'] без cancelled.
15
+ * БАНКЕТАМ.НЕТ: подписи «Банкет назначен» / «Банкет завершен»; изначально «Новая».
16
+ * БАНКЕТАМ.НЕТ (М2): фильтр ?status=, сортировка ORDER BY, LIMIT/OFFSET пагинация — в GET /requests.
17
+ *
18
+ * adminRequired — только login с role=admin из init.js
19
+ * PATCH body: { status, cancelReason? } — cancelReason только для cancelled
20
+ * После UPDATE — фронт перезагружает список load()
21
+ *
22
+ * Пример фильтра в SQL:
23
+ * const status = req.query.status;
24
+ * WHERE ($1::text IS NULL OR r.status = $1)
25
+ *
26
+ * GUIDE_PAGES.md §8.4 | AdminPage.jsx
27
+ * =============================================================================
28
+ */
2
29
  import { Router } from 'express';
3
30
  import { pool } from '../db/pool.js';
4
31
  import { authRequired, adminRequired } from '../middleware/auth.js';
5
32
 
6
33
  const router = Router();
7
34
 
8
- const ALLOWED_STATUSES = ['in_progress', 'completed', 'cancelled'];
35
+ const ALLOWED_STATUSES = ['in_progress', 'completed', 'cancelled']; // БАНКЕТАМ.НЕТ: убрать 'cancelled'
9
36
 
10
- // GET /api/admin/requests — все заявки для панели администратора
11
- router.get('/requests', authRequired, adminRequired, async (_req, res) => {
37
+ // GET /api/admin/requests — все заявки; ?status=new|in_progress|completed|cancelled (без all)
38
+ const FILTER_STATUSES = ['new', 'in_progress', 'completed', 'cancelled'];
39
+
40
+ router.get('/requests', authRequired, adminRequired, async (req, res) => {
12
41
  try {
42
+ const { status } = req.query;
43
+ const params = [];
44
+ let where = 'WHERE 1=1';
45
+
46
+ if (status && status !== 'all' && FILTER_STATUSES.includes(status)) {
47
+ params.push(status);
48
+ where += ` AND r.status = $${params.length}`;
49
+ }
50
+
13
51
  const { rows } = await pool.query(
14
52
  `SELECT r.*, st.name AS service_name, u.full_name AS user_full_name,
15
53
  u.phone AS user_phone, u.email AS user_email
16
54
  FROM requests r
17
55
  LEFT JOIN service_types st ON st.id = r.service_type_id
18
56
  JOIN users u ON u.id = r.user_id
19
- ORDER BY r.created_at DESC`
57
+ ${where}
58
+ ORDER BY r.created_at DESC`,
59
+ params
20
60
  );
21
61
  res.json(
22
62
  rows.map((row) => ({
@@ -1,4 +1,30 @@
1
-
1
+ /**
2
+ * =============================================================================
3
+ * ФАЙЛ: server/routes/auth.js
4
+ * POST /register, POST /login, GET /me
5
+ * =============================================================================
6
+ */
7
+
8
+ /**
9
+ * =============================================================================
10
+ * AUTH — /api/auth
11
+ * =============================================================================
12
+ * POST /register — новый user (поля: login, password, fullName, phone, email)
13
+ * POST /login — вход, возвращает JWT
14
+ * GET /me — текущий пользователь по токену
15
+ * ЗАМЕНИТЕ: INSERT в users при других полях регистрации
16
+ * БАНКЕТАМ.НЕТ (п.1–2): validateRegistration — логин/пароль по заданию; ошибка «Логин уже занят».
17
+ *
18
+ * register: bcrypt.hash → INSERT users → JWT (role user)
19
+ * login: SELECT по login → bcrypt.compare → JWT { id, login, role }
20
+ * me: authRequired не здесь — см. ниже GET /me с jwt.verify в этом файле
21
+ *
22
+ * Ответ register/login: { token, user: { id, login, fullName, role, … } }
23
+ * Ошибка 400: { errors: { login: '...' } } — фронт кладёт в errors state
24
+ *
25
+ * GUIDE_PAGES.md §8.1 | client/pages/RegisterPage, LoginPage
26
+ * =============================================================================
27
+ */
2
28
  import { Router } from 'express';
3
29
  import bcrypt from 'bcryptjs';
4
30
  import jwt from 'jsonwebtoken';
@@ -1,4 +1,27 @@
1
+ /**
2
+ * =============================================================================
3
+ * ФАЙЛ: server/routes/requests.js
4
+ * GET /mine, POST / — заявки пользователя. STATUS_LABELS — подписи статусов
5
+ * =============================================================================
6
+ */
1
7
 
8
+ /**
9
+ * =============================================================================
10
+ * REQUESTS — /api/requests (только role=user)
11
+ * =============================================================================
12
+ * GET /mine — история заявок текущего пользователя
13
+ * POST / — новая заявка
14
+ * STATUS_LABELS — подписи статусов на русском для фронта
15
+ * БАНКЕТАМ.НЕТ: in_progress → «Банкет назначен», completed → «Банкет завершен».
16
+ * БАНКЕТАМ.НЕТ: POST /api/requests/reviews/:id — отзыв (только если status !== 'new').
17
+ *
18
+ * mapRequest — snake_case из PG → camelCase для React (scheduledAt, serviceName…)
19
+ * POST /: body как на RequestFormPage; validateRequest в utils/validation.js
20
+ * user_id берётся из JWT (req.user.id), клиент не передаёт userId
21
+ *
22
+ * GUIDE_PAGES.md §8.2 | schema.sql таблица requests
23
+ * =============================================================================
24
+ */
2
25
  import { Router } from 'express';
3
26
  import { pool } from '../db/pool.js';
4
27
  import { authRequired } from '../middleware/auth.js';
@@ -7,10 +30,10 @@ import { validateRequest } from '../utils/validation.js';
7
30
  const router = Router();
8
31
 
9
32
  const STATUS_LABELS = {
10
- new: 'Новая',
11
- in_progress: 'В работе',
12
- completed: 'Выполнено',
13
- cancelled: 'Отменено',
33
+ new: 'Новая', // БАНКЕТАМ.НЕТ: без изменений
34
+ in_progress: 'В работе', // БАНКЕТАМ.НЕТ: 'Банкет назначен'
35
+ completed: 'Выполнено', // БАНКЕТАМ.НЕТ: 'Банкет завершен'
36
+ cancelled: 'Отменено', // БАНКЕТАМ.НЕТ: можно убрать
14
37
  };
15
38
 
16
39
  // GET /api/requests/mine — история заявок текущего пользователя
@@ -1,4 +1,24 @@
1
-
1
+ /**
2
+ * =============================================================================
3
+ * ФАЙЛ: server/routes/services.js
4
+ * GET /api/services — справочник для select на форме п.4
5
+ * =============================================================================
6
+ */
7
+
8
+ /**
9
+ * =============================================================================
10
+ * SERVICES — GET /api/services
11
+ * =============================================================================
12
+ * Справочник service_types — заполняется при npm run db:init из seed.sql.
13
+ * Фронт: RequestFormPage useEffect → api.getServices() → <select>.
14
+ *
15
+ * Менять список: server/db/seed.sql (пересоздать БД или UPDATE вручную).
16
+ * БАНКЕТАМ.НЕТ: id + name помещений (зал, ресторан, веранды…)
17
+ *
18
+ * Авторизация не нужна — справочник публичный.
19
+ * GUIDE_PAGES.md §8.3 | seed.sql
20
+ * =============================================================================
21
+ */
2
22
  import { Router } from 'express';
3
23
  import { pool } from '../db/pool.js';
4
24
 
@@ -1,4 +1,29 @@
1
+ /**
2
+ * =============================================================================
3
+ * ФАЙЛ: server/utils/validation.js
4
+ * Как client/src/utils/validation.js — те же правила!
5
+ * =============================================================================
6
+ */
1
7
 
8
+ /**
9
+ * =============================================================================
10
+ * ВАЛИДАЦИЯ НА СЕРВЕРЕ (обязательно дублировать на клиенте)
11
+ * =============================================================================
12
+ * ЗАМЕНИТЕ регулярки и тексты ошибок по критериям задания.
13
+ * =============================================================================
14
+ * БАНКЕТАМ.НЕТ (п.1): логин — латиница и цифры, min 6: LOGIN_REGEX = /^[a-zA-Z0-9]{6,}$/
15
+ * БАНКЕТАМ.НЕТ (п.1): пароль min 8 символов (сейчас 6).
16
+ * БАНКЕТАМ.НЕТ (п.4): дата ДД.ММ.ГГГГ — DATE_REGEX + parse в validateRequest.
17
+ * БАНКЕТАМ.НЕТ: убрать проверку isCustomService / custom_service если нет «иной услуги».
18
+ *
19
+ * Вызывается из routes перед INSERT — никогда не доверяйте только клиенту.
20
+ * Возвращает объект errors {}; пустой = ок. Роут отвечает res.status(400).json({ errors })
21
+ *
22
+ * Дубль на клиенте: client/src/utils/validation.js (те же REGEX и тексты)
23
+ *
24
+ * GUIDE_PAGES.md §7.1 | RegisterPage + RequestFormPage
25
+ * =============================================================================
26
+ */
2
27
 
3
28
  /** Формат телефона из задания — синхронизировать с formatPhoneInput на фронте */
4
29
  export const PHONE_REGEX = /^\+7\(\d{3}\)-\d{3}-\d{2}-\d{2}$/;
@@ -10,10 +35,10 @@ export function validateRegistration({ login, password, fullName, phone, email }
10
35
  const errors = {};
11
36
 
12
37
  if (!login?.trim()) errors.login = 'Логин обязателен';
13
- else if (login.trim().length < 3) errors.login = 'Логин не короче 3 символов';
38
+ else if (login.trim().length < 3) errors.login = 'Логин не короче 3 символов'; // БАНКЕТАМ.НЕТ: min 6 + только [a-zA-Z0-9]
14
39
 
15
40
  if (!password) errors.password = 'Пароль обязателен';
16
- else if (password.length < 6) errors.password = 'Пароль не менее 6 символов';
41
+ else if (password.length < 6) errors.password = 'Пароль не менее 6 символов'; // БАНКЕТАМ.НЕТ: < 8
17
42
 
18
43
  if (!fullName?.trim()) errors.fullName = 'ФИО обязательно';
19
44
  else if (!FIO_REGEX.test(fullName.trim())) errors.fullName = 'ФИО: только кириллица и пробелы';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mashka818/exam-de-template",
3
- "version": "1.0.1",
3
+ "version": "1.0.2",
4
4
  "description": "Шаблон ДЭ: exam-project + exam-guides. Экзамен: npx @mashka818/exam-de-template init",
5
5
  "license": "UNLICENSED",
6
6
  "type": "module",
@@ -1,4 +0,0 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" width="400" height="280" viewBox="0 0 400 280">
2
- <rect width="400" height="280" rx="16" fill="#e0f2f1"/>
3
- <text x="200" y="145" text-anchor="middle" fill="#0f766e" font-family="sans-serif" font-size="13">about-cleaning.png</text>
4
- </svg>
@@ -1 +0,0 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" width="360" height="80" viewBox="0 0 360 80"><rect width="360" height="80" rx="12" fill="#c4b5fd"/><text x="180" y="48" text-anchor="middle" fill="#4c1d95" font-size="12" font-family="sans-serif">admin-banner</text></svg>
@@ -1 +0,0 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" width="200" height="120" viewBox="0 0 200 120"><rect width="200" height="120" rx="8" fill="#f1f5f9"/><text x="100" y="65" text-anchor="middle" fill="#64748b" font-size="10" font-family="sans-serif">=5B 70O2>:</text></svg>
@@ -1,4 +0,0 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" width="120" height="120" viewBox="0 0 120 120">
2
- <rect width="120" height="120" rx="60" fill="#cbd5e1"/>
3
- <text x="60" y="65" text-anchor="middle" fill="#64748b" font-size="9" font-family="sans-serif">D>B> 1</text>
4
- </svg>
@@ -1,4 +0,0 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" width="120" height="120" viewBox="0 0 120 120">
2
- <rect width="120" height="120" rx="60" fill="#cbd5e1"/>
3
- <text x="60" y="65" text-anchor="middle" fill="#64748b" font-size="9" font-family="sans-serif">D>B> 2</text>
4
- </svg>
@@ -1,4 +0,0 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" width="120" height="120" viewBox="0 0 120 120">
2
- <rect width="120" height="120" rx="60" fill="#cbd5e1"/>
3
- <text x="60" y="65" text-anchor="middle" fill="#64748b" font-size="9" font-family="sans-serif">D>B> 3</text>
4
- </svg>
@@ -1,4 +0,0 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" width="360" height="160" viewBox="0 0 360 160">
2
- <rect width="360" height="160" rx="16" fill="#ccfbf1"/>
3
- <text x="180" y="85" text-anchor="middle" fill="#0f766e" font-family="sans-serif" font-size="14">home-hero  70<5=8B5 PNG 87 Figma</text>
4
- </svg>
@@ -1 +0,0 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" width="360" height="100" viewBox="0 0 360 100"><rect width="360" height="100" rx="12" fill="#cbd5e1"/><text x="180" y="55" text-anchor="middle" fill="#1e293b" font-size="12" font-family="sans-serif">login-banner</text></svg>
@@ -1,4 +0,0 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" width="120" height="40" viewBox="0 0 120 40">
2
- <rect width="120" height="40" rx="8" fill="#0d9488"/>
3
- <text x="60" y="26" text-anchor="middle" fill="white" font-family="sans-serif" font-size="11" font-weight="bold">>9 5 !0<</text>
4
- </svg>
@@ -1 +0,0 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" width="360" height="80" viewBox="0 0 360 80"><rect width="360" height="80" rx="12" fill="#a5f3fc"/><text x="180" y="48" text-anchor="middle" fill="#155e75" font-size="12" font-family="sans-serif">new-request-banner</text></svg>
@@ -1 +0,0 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" width="360" height="100" viewBox="0 0 360 100"><rect width="360" height="100" rx="12" fill="#99f6e4"/><text x="180" y="55" text-anchor="middle" fill="#134e4a" font-size="12" font-family="sans-serif">register-banner</text></svg>
@@ -1 +0,0 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" width="360" height="80" viewBox="0 0 360 80"><rect width="360" height="80" rx="12" fill="#5eead4"/><text x="180" y="48" text-anchor="middle" fill="#115e59" font-size="12" font-family="sans-serif">requests-banner</text></svg>
@@ -1,6 +0,0 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" width="800" height="400" viewBox="0 0 800 400">
2
- <defs><linearGradient id="g1" x1="0%" y1="0%" x2="100%" y2="100%"><stop offset="0%" style="stop-color:#0d9488"/><stop offset="100%" style="stop-color:#0891b2"/></linearGradient></defs>
3
- <rect width="800" height="400" fill="url(#g1)"/>
4
- <text x="400" y="200" text-anchor="middle" fill="white" font-family="sans-serif" font-size="22" font-weight="bold">1I89 :;8=8=3</text>
5
- <text x="400" y="230" text-anchor="middle" fill="#ccfbf1" font-size="14">slide-1.png  70<5=8B5 87 Figma</text>
6
- </svg>
@@ -1,5 +0,0 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" width="800" height="400" viewBox="0 0 800 400">
2
- <rect width="800" height="400" fill="#0f766e"/>
3
- <text x="400" y="200" text-anchor="middle" fill="white" font-family="sans-serif" font-size="22" font-weight="bold">5=5@0;L=0O C1>@:0</text>
4
- <text x="400" y="230" text-anchor="middle" fill="#99f6e4" font-size="14">slide-2.png</text>
5
- </svg>
@@ -1,5 +0,0 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" width="800" height="400" viewBox="0 0 800 400">
2
- <rect width="800" height="400" fill="#115e59"/>
3
- <text x="400" y="200" text-anchor="middle" fill="white" font-family="sans-serif" font-size="22" font-weight="bold">%8<G8AB:0 :>2@>2 8 <515;8</text>
4
- <text x="400" y="230" text-anchor="middle" fill="#a7f3d0" font-size="14">slide-3.png</text>
5
- </svg>
@@ -1,4 +0,0 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" width="400" height="280" viewBox="0 0 400 280">
2
- <rect width="400" height="280" rx="16" fill="#e0f2f1"/>
3
- <text x="200" y="145" text-anchor="middle" fill="#0f766e" font-family="sans-serif" font-size="13">about-cleaning.png</text>
4
- </svg>
@@ -1 +0,0 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" width="360" height="80" viewBox="0 0 360 80"><rect width="360" height="80" rx="12" fill="#c4b5fd"/><text x="180" y="48" text-anchor="middle" fill="#4c1d95" font-size="12" font-family="sans-serif">admin-banner</text></svg>
@@ -1 +0,0 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" width="200" height="120" viewBox="0 0 200 120"><rect width="200" height="120" rx="8" fill="#f1f5f9"/><text x="100" y="65" text-anchor="middle" fill="#64748b" font-size="10" font-family="sans-serif">=5B 70O2>:</text></svg>
@@ -1,4 +0,0 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" width="120" height="120" viewBox="0 0 120 120">
2
- <rect width="120" height="120" rx="60" fill="#cbd5e1"/>
3
- <text x="60" y="65" text-anchor="middle" fill="#64748b" font-size="9" font-family="sans-serif">D>B> 1</text>
4
- </svg>
@@ -1,4 +0,0 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" width="120" height="120" viewBox="0 0 120 120">
2
- <rect width="120" height="120" rx="60" fill="#cbd5e1"/>
3
- <text x="60" y="65" text-anchor="middle" fill="#64748b" font-size="9" font-family="sans-serif">D>B> 2</text>
4
- </svg>
@@ -1,4 +0,0 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" width="120" height="120" viewBox="0 0 120 120">
2
- <rect width="120" height="120" rx="60" fill="#cbd5e1"/>
3
- <text x="60" y="65" text-anchor="middle" fill="#64748b" font-size="9" font-family="sans-serif">D>B> 3</text>
4
- </svg>
@@ -1,4 +0,0 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" width="360" height="160" viewBox="0 0 360 160">
2
- <rect width="360" height="160" rx="16" fill="#ccfbf1"/>
3
- <text x="180" y="85" text-anchor="middle" fill="#0f766e" font-family="sans-serif" font-size="14">home-hero  70<5=8B5 PNG 87 Figma</text>
4
- </svg>
@@ -1 +0,0 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" width="360" height="100" viewBox="0 0 360 100"><rect width="360" height="100" rx="12" fill="#cbd5e1"/><text x="180" y="55" text-anchor="middle" fill="#1e293b" font-size="12" font-family="sans-serif">login-banner</text></svg>
@@ -1,4 +0,0 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" width="120" height="40" viewBox="0 0 120 40">
2
- <rect width="120" height="40" rx="8" fill="#0d9488"/>
3
- <text x="60" y="26" text-anchor="middle" fill="white" font-family="sans-serif" font-size="11" font-weight="bold">>9 5 !0<</text>
4
- </svg>
@@ -1 +0,0 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" width="360" height="80" viewBox="0 0 360 80"><rect width="360" height="80" rx="12" fill="#a5f3fc"/><text x="180" y="48" text-anchor="middle" fill="#155e75" font-size="12" font-family="sans-serif">new-request-banner</text></svg>
@@ -1 +0,0 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" width="360" height="100" viewBox="0 0 360 100"><rect width="360" height="100" rx="12" fill="#99f6e4"/><text x="180" y="55" text-anchor="middle" fill="#134e4a" font-size="12" font-family="sans-serif">register-banner</text></svg>
@@ -1 +0,0 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" width="360" height="80" viewBox="0 0 360 80"><rect width="360" height="80" rx="12" fill="#5eead4"/><text x="180" y="48" text-anchor="middle" fill="#115e59" font-size="12" font-family="sans-serif">requests-banner</text></svg>
@@ -1,6 +0,0 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" width="800" height="400" viewBox="0 0 800 400">
2
- <defs><linearGradient id="g1" x1="0%" y1="0%" x2="100%" y2="100%"><stop offset="0%" style="stop-color:#0d9488"/><stop offset="100%" style="stop-color:#0891b2"/></linearGradient></defs>
3
- <rect width="800" height="400" fill="url(#g1)"/>
4
- <text x="400" y="200" text-anchor="middle" fill="white" font-family="sans-serif" font-size="22" font-weight="bold">1I89 :;8=8=3</text>
5
- <text x="400" y="230" text-anchor="middle" fill="#ccfbf1" font-size="14">slide-1.png  70<5=8B5 87 Figma</text>
6
- </svg>
@@ -1,5 +0,0 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" width="800" height="400" viewBox="0 0 800 400">
2
- <rect width="800" height="400" fill="#0f766e"/>
3
- <text x="400" y="200" text-anchor="middle" fill="white" font-family="sans-serif" font-size="22" font-weight="bold">5=5@0;L=0O C1>@:0</text>
4
- <text x="400" y="230" text-anchor="middle" fill="#99f6e4" font-size="14">slide-2.png</text>
5
- </svg>
@@ -1,5 +0,0 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" width="800" height="400" viewBox="0 0 800 400">
2
- <rect width="800" height="400" fill="#115e59"/>
3
- <text x="400" y="200" text-anchor="middle" fill="white" font-family="sans-serif" font-size="22" font-weight="bold">%8<G8AB:0 :>2@>2 8 <515;8</text>
4
- <text x="400" y="230" text-anchor="middle" fill="#a7f3d0" font-size="14">slide-3.png</text>
5
- </svg>