diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..a4e25b2 --- /dev/null +++ b/Makefile @@ -0,0 +1,4 @@ +build: + npm run build + rm -rf ../pinned_message/cmd/pinned_message/static/user + cp -r dist ../pinned_message/cmd/pinned_message/static/user diff --git a/src/App.vue b/src/App.vue index 7905b05..ae00c6a 100644 --- a/src/App.vue +++ b/src/App.vue @@ -1,85 +1,13 @@ - - - - - - - - Home - About - - - - - + + + diff --git a/src/assets/main.css b/src/assets/main.css index 36fb845..d5b802c 100644 --- a/src/assets/main.css +++ b/src/assets/main.css @@ -3,7 +3,7 @@ #app { max-width: 1280px; margin: 0 auto; - padding: 2rem; + padding: 1rem; font-weight: normal; } diff --git a/src/components/SchedulePage.vue b/src/components/SchedulePage.vue new file mode 100644 index 0000000..b2e55c4 --- /dev/null +++ b/src/components/SchedulePage.vue @@ -0,0 +1,59 @@ + + + + + + {{ capitalizeFirstLetter(formatRussianDate(day.date)) }} + ({{ getRelativeDayName(day.date) }}) + + + {{ performance.time_collection }} + + + {{ performance.time_start }} + + + Место: {{ capitalizeFirstLetter(performance.place) }} + + + {{ capitalizeFirstLetter(performance.name) }} + + + Номера: + + - {{ number.name }} + + + + {{ capitalizeFirstLetter(performance.costumes) }} + + + + + + + diff --git a/src/components/client.ts b/src/components/client.ts new file mode 100644 index 0000000..ebc240e --- /dev/null +++ b/src/components/client.ts @@ -0,0 +1,27 @@ +import type { Schedule } from './models' + +export const apiGetDays = async (): Promise => { + try { + const response = await fetch(getApiUrl('/schedule'), { method: 'GET' }) + if (!response.ok) { + throw new Error(`http error status: ${response.status}`) + } + return await response.json() + } catch (error) { + console.error('[apiGetDays] error:', error) + throw error + } +} + +export function getApiUrl(path: string) { + const url = 'http://' + window.location.host.split(':')[0] + ':8090' + path + return url +} + +export function encodeUTF8ToBase64(s: string) { + return btoa( + encodeURIComponent(s).replace(/%([0-9A-F]{2})/g, (_, p1) => + String.fromCharCode(parseInt(p1, 16)), + ), + ) +} diff --git a/src/components/date.ts b/src/components/date.ts new file mode 100644 index 0000000..8d724db --- /dev/null +++ b/src/components/date.ts @@ -0,0 +1,75 @@ +export function formatRussianDate(dateStr: string): string { + // 1. Вытаскиваем только саму дату (2026-03-24) с помощью регулярного выражения + // Это защитит нас от багов с часовыми поясами при парсинге + const match = dateStr.match(/^(\d{4})-(\d{2})-(\d{2})/); + if (!match) { + throw new Error("Неверный формат входной строки"); + } + + // 2. Преобразуем строки в числа + const year = parseInt(match[1], 10); + const month = parseInt(match[2], 10); + const day = parseInt(match[3], 10); + + // 3. Создаем объект даты (обратите внимание: в JS месяцы начинаются с 0, поэтому month - 1) + const dateObj = new Date(year, month - 1, day); + + // 4. Словари для точного форматирования (родительный падеж для месяцев) + const monthsRu = [ + "января", "февраля", "марта", "апреля", "мая", "июня", + "июля", "августа", "сентября", "октября", "ноября", "декабря" + ]; + + // В JS 0 - это воскресенье, 1 - понедельник и т.д. + const weekdaysRu = [ + "воскресенье", "понедельник", "вторник", "среда", + "четверг", "пятница", "суббота" + ]; + + // 5. Получаем нужные значения + const monthName = monthsRu[dateObj.getMonth()]; + const weekdayName = weekdaysRu[dateObj.getDay()]; + + // 6. Собираем итоговую строку + return `${weekdayName} ${day} ${monthName}`; +} + +export function getRelativeDayName(dateStr: string): string { + // 1. Вытаскиваем только дату (например, 2026-03-24) + const match = dateStr.match(/^(\d{4})-(\d{2})-(\d{2})/); + if (!match) { + throw new Error("Неверный формат входной строки"); + } + + const year = parseInt(match[1], 10); + const month = parseInt(match[2], 10) - 1; // Месяцы в JS начинаются с 0 + const day = parseInt(match[3], 10); + + // 2. Создаем объект целевой даты и сбрасываем время в 00:00:00 + const targetDate = new Date(year, month, day, 0, 0, 0, 0); + + // 3. Создаем объект СЕГОДНЯШНЕЙ даты и тоже сбрасываем время в 00:00:00 + const today = new Date(); + today.setHours(0, 0, 0, 0); + + // 4. Вычисляем разницу в миллисекундах и переводим в дни + // Используем Math.round, чтобы избежать багов при переходе на летнее/зимнее время + const diffInMs = targetDate.getTime() - today.getTime(); + const diffInDays = Math.round(diffInMs / (1000 * 60 * 60 * 24)); + + // 5. Возвращаем результат в зависимости от разницы в днях + switch (diffInDays) { + case 0: + return "сегодня"; + case 1: + return "завтра"; + case 2: + return "послезавтра"; // бонус :) + case -1: + return "вчера"; // бонус :) + default: + // Если это не сегодня и не завтра, можно вернуть пустую строку, + // либо просто количество дней, либо отформатированную дату (как в прошлом ответе) + return ""; + } +} diff --git a/src/components/models.ts b/src/components/models.ts new file mode 100644 index 0000000..1acdcc0 --- /dev/null +++ b/src/components/models.ts @@ -0,0 +1,21 @@ +export type Schedule = { + days: Day[] +} + +export type Day = { + date: string + performances: Performance[] +} + +export type Performance = { + time_collection: string + time_start: string + place: string + name: string + numbers: Number[] + costumes: string +} + +export type Number = { + name: string +} diff --git a/src/components/text.ts b/src/components/text.ts new file mode 100644 index 0000000..95cfd87 --- /dev/null +++ b/src/components/text.ts @@ -0,0 +1,9 @@ +export function capitalizeFirstLetter(str: string): string { + // Проверка на пустую строку, чтобы избежать ошибок + if (!str) { + return str; + } + + // Берем первый символ, делаем его большим + приклеиваем остаток строки (начиная со 2-го символа) + return str.charAt(0).toUpperCase() + str.slice(1); +}