Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

- changed timetable date format to iso #205

Merged
merged 1 commit into from
Mar 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 9 additions & 9 deletions src/api/controllers/TimetableApi.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { stringifyDateIso, getDateWithDayOffset } from './../../utils/date';
import { stringifyDate, getDateWithDayOffset } from './../../utils/date';
import { timetableEventApi, GetEventsParams } from './../timetable/TimetableEventApi';
import { timetableRoomApi } from './../timetable/TimetableRoomApi';
import { useTimetableStore } from './../../store/timetable';
Expand Down Expand Up @@ -44,8 +44,8 @@ export class TimetableApi {
public static async getDayEvents(date: Date, groupId: number) {
const { setDay } = useTimetableStore();
const { data } = await timetableEventApi.getAll({
start: stringifyDateIso(date),
end: stringifyDateIso(getDateWithDayOffset(date, 1)),
start: stringifyDate(date),
end: stringifyDate(getDateWithDayOffset(date, 1)),
group_id: groupId,
});
setDay(date, data.items);
Expand All @@ -54,25 +54,25 @@ export class TimetableApi {
public static async getLecturerEvents(lecturerId: number) {
const { setLecturerEvents, setLecturers } = useTimetableStore();
const { data } = await timetableEventApi.getAll({
start: stringifyDateIso(new Date()),
end: stringifyDateIso(getDateWithDayOffset(new Date(), 1)),
start: stringifyDate(new Date()),
end: stringifyDate(getDateWithDayOffset(new Date(), 1)),
lecturer_id: lecturerId,
});
if (data.items.length) {
setLecturers(data.items[0].lecturers);
setLecturers(data.items[0].lecturer);
setLecturerEvents(lecturerId, data.items);
}
}

public static async getRoomEvents(roomId: number) {
const { setRoomEvents, setRooms } = useTimetableStore();
const { data } = await timetableEventApi.getAll({
start: stringifyDateIso(new Date()),
end: stringifyDateIso(getDateWithDayOffset(new Date(), 1)),
start: stringifyDate(new Date()),
end: stringifyDate(getDateWithDayOffset(new Date(), 1)),
room_id: roomId,
});
if (data.items.length) {
setRooms(data.items[0].rooms);
setRooms(data.items[0].room);
setRoomEvents(roomId, data.items);
}
}
Expand Down
6 changes: 3 additions & 3 deletions src/api/models/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ export interface StudyGroup extends Entity {

export interface Event extends Entity {
name: string;
rooms: Room[];
groups: StudyGroup[];
lecturers: Lecturer[];
room: Room[];
group: StudyGroup[];
lecturer: Lecturer[];
start_ts: string;
end_ts: string;
}
Expand Down
4 changes: 2 additions & 2 deletions src/components/EmailPasswordForm.vue
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ const props = defineProps<{
mode: 'login' | 'register';
}>();

const emits = defineEmits<{
const emit = defineEmits<{
submit: [data: SubmitData];
}>();

Expand All @@ -30,7 +30,7 @@ async function submitHandler(event: Event) {

if (password === repeat_password || props.mode === 'login') {
if (email && password) {
emits('submit', { email, password });
emit('submit', { email, password });
}
} else {
checkPasswords.value = true;
Expand Down
6 changes: 3 additions & 3 deletions src/components/EventRow.vue
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,15 @@ const info = computed(() => {
const arr: string[] = [];

if (props.info.includes('room')) {
arr.push(props.event.rooms?.map(room => room.name).join(', '));
arr.push(props.event.room?.map(room => room.name).join(', '));
}

if (props.info.includes('lecturer')) {
arr.push(props.event.lecturers?.map(lecturer => getNameWithInitials(lecturer)).join(', '));
arr.push(props.event.lecturer?.map(lecturer => getNameWithInitials(lecturer)).join(', '));
}

if (props.info.includes('group')) {
arr.push(props.event.groups.map(group => group.number).join(', '));
arr.push(props.event.group.map(group => group.number).join(', '));
}

return arr.filter(c => Boolean(c)).join(' • ');
Expand Down
71 changes: 48 additions & 23 deletions src/components/IrdomCalendar.vue
Original file line number Diff line number Diff line change
@@ -1,25 +1,49 @@
<script setup lang="ts">
import { stringifyDate } from '@/utils/date';
import { computed, ref } from 'vue';

const weekdays = ['пн', 'вт', 'ср', 'чт', 'пт', 'сб', 'вс'];

const props = defineProps<{ selected: Date; modelValue: Date }>();
const emits = defineEmits<{ 'update:modelValue': [value: Date] }>();

const getDays = (date: Date) => new Date(date.getFullYear(), date.getMonth() + 1, 0).getDate();
const getItemDate = (day: number) =>
new Date(props.modelValue.getFullYear(), props.modelValue.getMonth(), day);
const getItemStringDate = (day: number) => stringifyDate(getItemDate(day));
const isCurrent = (day: number) => getItemStringDate(day) === stringifyDate(props.selected);
const isToday = (day: number) => getItemStringDate(day) === stringifyDate(new Date());
const getAriaLabel = (day: number) =>
getItemDate(day).toLocaleDateString('ru-RU', { day: 'numeric', month: 'long', year: 'numeric' });

const changeMonthHandler = (offset: number) => {
const d = new Date(props.modelValue);
d.setMonth(d.getMonth() + offset);
emits('update:modelValue', d);
};
const props = defineProps<{ modelValue: Date }>();
const emit = defineEmits<{ 'update:modelValue': [value: Date] }>();

const date = ref(props.modelValue);
const numberOfDays = computed(() =>
new Date(date.value.getFullYear(), date.value.getMonth() + 1, 0).getDate()
);

function changeMonthHandler(delta: number) {
date.value = new Date(
date.value.getFullYear(),
date.value.getMonth() + delta,
date.value.getDate()
);
}

function getItemDate(i: number) {
console.log(i, stringifyDate(new Date(date.value.getFullYear(), date.value.getMonth(), i)));
return new Date(date.value.getFullYear(), date.value.getMonth(), i);
}

function getItemStringDate(i: number) {
return stringifyDate(getItemDate(i));
}

function isToday(i: number) {
return stringifyDate(new Date()) === getItemStringDate(i);
}

function isCurrent(i: number) {
return stringifyDate(props.modelValue) === getItemStringDate(i);
}

function getAriaLabel(i: number) {
return getItemDate(i).toLocaleDateString('ru-RU');
}

function itemClickHandler(i: number) {
emit('update:modelValue', new Date(date.value.getFullYear(), date.value.getMonth(), i));
}
</script>

<template>
Expand All @@ -36,7 +60,7 @@ const changeMonthHandler = (offset: number) => {
</button>

<span class="noselect">
{{ modelValue.toLocaleDateString('ru-RU', { month: 'long', year: 'numeric' }) }}
{{ date.toLocaleDateString('ru-RU', { month: 'long', year: 'numeric' }) }}
</span>

<button
Expand All @@ -57,18 +81,19 @@ const changeMonthHandler = (offset: number) => {
class="grid"
>
<span v-for="weekday of weekdays" :key="weekday" class="noselect weekday">{{ weekday }}</span>
<RouterLink
v-for="i in getDays(modelValue)"
<button
v-for="i in numberOfDays"
:key="i"
v-ripple
type="button"
class="day"
:to="`/timetable/${getItemStringDate(i)}`"
:class="['day', { current: isCurrent(i), today: isToday(i) && !isCurrent(i) }]"
:class="{ current: isCurrent(i), today: isToday(i) && !isCurrent(i) }"
:style="{ 'grid-column': i === 1 ? getItemDate(i).getDay() : 'unset' }"
:aria-label="getAriaLabel(i)"
@click="itemClickHandler(i)"
>
{{ i }}
</RouterLink>
</button>
</div>
</div>
</template>
Expand Down
2 changes: 1 addition & 1 deletion src/router/timetable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export const timetableRoutes: RouteRecordRaw[] = [
redirect: `/timetable/${stringifyDate(new Date())}`,
},
{
path: ':date(\\d{2}-\\d{2}-\\d{4})',
path: ':date(\\d{4}-\\d{2}-\\d{2})',
component: TimetableView,
},
{
Expand Down
20 changes: 1 addition & 19 deletions src/utils/date.test.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,7 @@
import { describe, it, expect } from 'vitest';
import {
parseDate,
stringifyDate,
getWeekdayName,
getDateWithDayOffset,
stringifyDateIso,
} from './date';
import { getWeekdayName, getDateWithDayOffset } from './date';

describe('Convert date functions:', () => {
it('should parse/stringify date by common format dd-mm-yyyy', () => {
expect(parseDate('01-07-2003')).toEqual(new Date(2003, 6, 1));
expect(stringifyDate(new Date(2003, 6, 1))).toBe('01-07-2003');

expect(parseDate(stringifyDate(new Date(2003, 6, 1)))).toEqual(new Date(2003, 6, 1));
expect(stringifyDate(parseDate('01-07-2003'))).toBe('01-07-2003');
});

it('should return correct weekday names', () => {
expect(getWeekdayName(new Date(2023, 2, 13)).toLowerCase()).toBe('пн');
expect(getWeekdayName(new Date(2023, 2, 14)).toLowerCase()).toBe('вт');
Expand Down Expand Up @@ -44,8 +30,4 @@ describe('Convert date functions:', () => {
expect(getWeekdayName(getDateWithDayOffset(date, -5))).toBe('ср');
expect(getWeekdayName(getDateWithDayOffset(date, -6))).toBe('вт');
});

it('should correct stringify date to ISO format', () => {
expect(stringifyDateIso(new Date(2023, 2, 13))).toBe('2023-03-13');
});
});
18 changes: 2 additions & 16 deletions src/utils/date.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,23 +10,9 @@ export const getDateWithDayOffset = (date: Date, offset: number) => {
return d;
};

export const parseDate = (value: string) => {
const [day, month, year] = value.split('-').map(v => Number(v));
return new Date(year, month - 1, day);
};

export const stringifyDate = (date: Date) => {
const day = date.getDate();
const month = date.getMonth();
const year = date.getFullYear();

return `${lz(day)}-${lz(month + 1)}-${year}`;
};

export const stringifyDateIso = (date: Date) => {
const day = date.getDate();
const month = date.getMonth();
const month = date.getMonth() + 1;
const year = date.getFullYear();

return `${year}-${lz(month + 1)}-${lz(day)}`;
return `${year}-${lz(month)}-${lz(day)}`;
};
17 changes: 13 additions & 4 deletions src/views/timetable/CalendarDropdown.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,17 @@
import { ref } from 'vue';
import { useTimetableStore } from '@/store/timetable';
import IrdomCalendar from '@/components/IrdomCalendar.vue';
import { useRouter } from 'vue-router';
import { stringifyDate } from '@/utils/date';

const props = defineProps<{ date: Date }>();

const { group } = useTimetableStore();
const router = useRouter();

const show = ref(false);
const expander = ref<HTMLButtonElement | null>(null);
const calendar = ref<HTMLDivElement | null>(null);
const { group } = useTimetableStore();

const props = defineProps<{ date: Date }>();

const innerDate = ref(props.date);
const expanderClickHandler = () => {
Expand All @@ -28,6 +32,11 @@ const clickOutsideHandler = (e: MouseEvent) => {
innerDate.value = props.date;
}
};

function updateDateHandler(date: Date) {
show.value = false;
router.push(`/timetable/${stringifyDate(date)}`);
}
</script>

<template>
Expand Down Expand Up @@ -57,7 +66,7 @@ const clickOutsideHandler = (e: MouseEvent) => {
:style="{ transform: `scaleY(${+show})` }"
class="dropdown"
>
<IrdomCalendar v-model="innerDate" :selected="date" />
<IrdomCalendar v-model="innerDate" :selected="date" @update:model-value="updateDateHandler" />
</div>
</template>

Expand Down
4 changes: 2 additions & 2 deletions src/views/timetable/TimetableView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { computed, ref, watch } from 'vue';
import AsyncEventsList from './AsyncEventsList.vue';
import CalendarDropdown from './CalendarDropdown.vue';
import { useTimetableStore } from '@/store/timetable';
import { parseDate, stringifyDate, getDateWithDayOffset } from '@/utils/date';
import { stringifyDate, getDateWithDayOffset } from '@/utils/date';
import { LocalStorage, LocalStorageItem } from '@/models/LocalStorage';
import { ToolbarActionItem, ToolbarMenuItem } from '@/components/IrdomToolbar.vue';
import IrdomLayout from '@/components/IrdomLayout.vue';
Expand Down Expand Up @@ -39,7 +39,7 @@ const toolbarMenu: ToolbarMenuItem[] = [
];

const date = computed(() => {
return parseDate(route.params.date as string);
return new Date(route.params.date as string);
});

// HACK: на каждое изменение даты обновляем компонент Suspense
Expand Down
8 changes: 4 additions & 4 deletions src/views/timetable/event/AsyncContent.vue
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@ interface Lecturer {
const lecturers = computed(() => {
const arr: Lecturer[] = [];

if (event.value?.lecturers) {
for (const { id, first_name, middle_name, last_name } of event.value.lecturers) {
if (event.value?.lecturer) {
for (const { id, first_name, middle_name, last_name } of event.value.lecturer) {
arr.push({
id,
title: lecturerTitle({ first_name, middle_name, last_name }),
Expand All @@ -73,7 +73,7 @@ const lecturers = computed(() => {
<template>
<h2 class="h2">{{ event?.name }}</h2>

<DataRow title="Группа" :info="event?.groups.map(g => g.number).join(', ')" class="row">
<DataRow title="Группа" :info="event?.group.map(g => g.number).join(', ') ?? ''" class="row">
<v-icon icon="group" class="icon" />
</DataRow>

Expand All @@ -82,7 +82,7 @@ const lecturers = computed(() => {
</DataRow>

<DataRow
v-for="{ name, id: roomId } of event?.rooms"
v-for="{ name, id: roomId } of event?.room"
:key="roomId"
:title="name"
class="row"
Expand Down