Skip to content

Commit d243bec

Browse files
authored
Merge pull request #15 from MarkMelior/feature/VEES-22-view-post-vees
VEES-22 | Страница просмотра тренировки
2 parents 4c861af + 6f559a7 commit d243bec

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+377
-109
lines changed
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import { veesResponse } from './vees.response';
2+
3+
export const getVeesByIdResponse = async (id: string) => {
4+
const veesList = await veesResponse();
5+
6+
return veesList?.find((vees) => vees.id === id);
7+
};

persist-storage/mock/VEES_ACTIVE.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
import type { IVeesDto } from '@/entities/vees';
1+
import type { IVeesDto } from '@/shared/types';
22

3-
export const VEES_ACTIVE: IVeesDto = {
3+
export const VEES_ACTIVE: Omit<IVeesDto, 'id'> = {
44
duration: {
55
from: '2025-01-12T10:00:00',
66
to: '2025-01-12T11:00:00',

persist-storage/mock/VEES_LIST.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { IVeesDto } from '@/entities/vees';
1+
import type { IVeesDto } from '@/shared/types';
22

33
export const VEES_LIST: IVeesDto[] = [
44
{
@@ -17,6 +17,7 @@ export const VEES_LIST: IVeesDto[] = [
1717
},
1818
],
1919
exerciseTemplateId: 'template-saturday',
20+
id: 'c3dce3ed-cedf-4d1f-b907-927e24314f02',
2021
},
2122
{
2223
duration: {
@@ -34,6 +35,7 @@ export const VEES_LIST: IVeesDto[] = [
3435
},
3536
],
3637
exerciseTemplateId: 'template-tuesday',
38+
id: 'd3dce3ed-cedf-4d1f-b907-927e24314f02',
3739
},
3840
{
3941
duration: {
@@ -51,6 +53,7 @@ export const VEES_LIST: IVeesDto[] = [
5153
},
5254
],
5355
exerciseTemplateId: 'template-saturday',
56+
id: '7e040e20-61e0-4c2c-818a-192df8fc2cae',
5457
},
5558
{
5659
duration: {
@@ -68,6 +71,7 @@ export const VEES_LIST: IVeesDto[] = [
6871
},
6972
],
7073
exerciseTemplateId: 'template-saturday',
74+
id: '9ae9be94-3514-487a-920f-802d2a76f804',
7175
},
7276
{
7377
duration: {
@@ -88,6 +92,7 @@ export const VEES_LIST: IVeesDto[] = [
8892
},
8993
],
9094
exerciseTemplateId: 'template-tuesday',
95+
id: '64f5d700-2ae9-4f53-8d9c-43fe90f63d32',
9196
},
9297
{
9398
duration: {
@@ -108,5 +113,6 @@ export const VEES_LIST: IVeesDto[] = [
108113
},
109114
],
110115
exerciseTemplateId: 'template-tuesday',
116+
id: '64f5d700-2ae9-4f53-8d9c-43fe90f63d33',
111117
},
112118
];
Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,23 @@
11
import localforage from 'localforage';
2+
import { nanoid } from 'nanoid';
23

34
import { StorageKey } from '@/shared/constants';
4-
5-
import type { IVeesDto } from '@/entities/vees';
5+
import type { IVeesDto } from '@/shared/types';
66

77
import { removeVeesActiveRequest } from './remove-vees-active.request';
88
import { veesListResponse } from './vees-list.response';
99

10-
export const saveVeesActiveRequest = async (payload: IVeesDto) => {
10+
export const saveVeesActiveRequest = async (payload: Omit<IVeesDto, 'id'>) => {
1111
const veesList
1212
= await localforage.getItem<IVeesDto[]>(StorageKey.VEES_LIST) ?? [];
1313

14+
const payloadWithId = {
15+
...payload,
16+
id: nanoid(),
17+
};
18+
1419
await removeVeesActiveRequest();
15-
await localforage.setItem<IVeesDto[]>(StorageKey.VEES_LIST, [...veesList, payload]);
20+
await localforage.setItem<IVeesDto[]>(StorageKey.VEES_LIST, [...veesList, payloadWithId]);
1621

1722
return await veesListResponse();
1823
};

persist-storage/utils/vees.utils.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1+
import type { IVeesDto, IVeesResponse } from '@/shared/types';
2+
13
import type { IExerciseGroupsDto } from '@/entities/exercise-groups';
24
import type { IExerciseTemplatesDto } from '@/entities/exercise-templates';
3-
import type { IVeesDto, IVeesResponse } from '@/entities/vees';
45

56
export const createExerciseGroupsMap = (
67
exerciseGroups: IExerciseGroupsDto[],

persist-storage/vees-active.response.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import localforage from 'localforage';
22

33
import { StorageKey } from '@/shared/constants';
4+
import type { IVeesDto, IVeesResponse } from '@/shared/types';
45

56
import type { IExerciseGroupsDto } from '@/entities/exercise-groups';
67
import type { IExerciseTemplatesDto } from '@/entities/exercise-templates';
7-
import type { IVeesDto, IVeesResponse } from '@/entities/vees';
88

99
import {
1010
createExerciseGroupsMap,
@@ -39,6 +39,7 @@ export const veesActiveResponse = async (): Promise<IVeesResponse | null> => {
3939
exerciseGroupsMap,
4040
0,
4141
),
42+
id: veesActive.id,
4243
number: 1,
4344
};
4445
};

persist-storage/vees-list.response.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import { compareResults } from '@/shared/lib/compare-results';
2-
3-
import type { IVeesListResponse, IVeesResponse } from '@/entities/vees';
2+
import type { IVeesListResponse, IVeesResponse } from '@/shared/types';
43

54
import { veesResponse } from './vees.response';
65

@@ -10,6 +9,7 @@ const mapVeesResponseToList = (data: IVeesResponse): IVeesListResponse => ({
109
duration: data.duration,
1110
exerciseCount: data.exercises.length, // Количество упражнений
1211
exerciseTemplate: data.exerciseTemplate, // Шаблон упражнения, если есть
12+
id: data.id,
1313
number: data.number, // Номер тренировки
1414
resultDownCount: data.exercises.reduce(
1515
(sum, exercise) =>

persist-storage/vees.response.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import localforage from 'localforage';
22

33
import { StorageKey } from '@/shared/constants';
4+
import type { IVeesDto, IVeesResponse } from '@/shared/types';
45

56
import type { IExerciseGroupsDto } from '@/entities/exercise-groups';
67
import type { IExerciseTemplatesDto } from '@/entities/exercise-templates';
7-
import type { IVeesDto, IVeesResponse } from '@/entities/vees';
88

99
import {
1010
createExerciseGroupsMap,
@@ -37,6 +37,7 @@ export const veesResponse = async (): Promise<IVeesResponse[] | null> => {
3737
exerciseGroupsMap,
3838
index,
3939
),
40+
id: vees.id,
4041
number: index + 1,
4142
})).reverse();
4243
};

src/app/(with-navbar)/client/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import { Badge, Button, Flex, Layout, Separator } from '@/shared/ui';
1111
import { FiltersModal } from '@/features/FiltersModal';
1212
import { SortModal } from '@/features/SortModal';
1313

14-
import { useVeesList } from '@/entities/vees';
14+
import { useVeesList } from '@/entities/vees-list';
1515

1616
import styles from '../page.module.scss';
1717

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
'use client';
2+
3+
import { useEffect } from 'react';
4+
5+
import { Card } from '@/widgets/Card';
6+
import { Headers } from '@/widgets/Headers';
7+
8+
import { PaperOutlineIcon, StopwatchOutlineIcon } from '@/shared/icons';
9+
import { getDateInfo, getDateRangeDuration } from '@/shared/lib/date';
10+
import { Alert, Chip, Layout, List, Separator, Skeleton } from '@/shared/ui';
11+
import { InfoBlock } from '@/shared/ui/client';
12+
13+
import { useVees } from '@/entities/vees';
14+
15+
interface IClientRender {
16+
id: string
17+
}
18+
19+
export const ClientRender = ({ id }: IClientRender) => {
20+
const { dataVees, errorVees, loadingVees, onGetVeesById } = useVees();
21+
22+
useEffect(() => {
23+
onGetVeesById(id);
24+
}, []);
25+
26+
if (loadingVees) {
27+
return (
28+
<>
29+
<Skeleton height={65} isAnimated={false} radius="none" />
30+
<Separator size={18} />
31+
<Layout>
32+
<Skeleton height={216} />
33+
<Separator size={32} />
34+
<Skeleton.List />
35+
</Layout>
36+
</>
37+
);
38+
}
39+
40+
if (errorVees) {
41+
return (
42+
<Alert
43+
closable={false}
44+
content="Ошибка загрузки тренировки!"
45+
description={errorVees.message}
46+
type="error"
47+
/>
48+
);
49+
}
50+
51+
if (!dataVees) {
52+
return;
53+
}
54+
55+
const {
56+
duration,
57+
exercises,
58+
exerciseTemplate,
59+
number,
60+
} = dataVees;
61+
62+
const { hours: hoursFrom, minutes: minutesFrom } = getDateInfo(duration.from);
63+
const { day, hours: hoursTo, minutes: minutesTo, monthName } = getDateInfo(duration.to);
64+
65+
const rangeDuration = getDateRangeDuration(duration.from, duration.to);
66+
67+
return (
68+
<>
69+
<Headers.VeesPost title={`${day} ${monthName}`} />
70+
<main>
71+
<Layout>
72+
<InfoBlock>
73+
<List.Item
74+
description={`${hoursFrom}:${minutesFrom} - ${hoursTo}:${minutesTo}`}
75+
icon={<StopwatchOutlineIcon />}
76+
title="Длительность тренировки"
77+
value={rangeDuration}
78+
/>
79+
<List.Item
80+
icon={<PaperOutlineIcon />}
81+
title="Шаблон тренировки"
82+
value={(
83+
<Chip.Category
84+
className="mt-1"
85+
customColor={exerciseTemplate?.color}
86+
isEdited={true}
87+
name={exerciseTemplate?.name ?? 'Пользовательская тренировка'}
88+
number={exerciseTemplate?.number}
89+
size="medium"
90+
/>
91+
)}
92+
/>
93+
<List.Horizontal
94+
items={[
95+
{ title: 'Тренировка №', value: number },
96+
{ title: 'Упражнений', value: exercises.length },
97+
]}
98+
showDivider={false}
99+
/>
100+
</InfoBlock>
101+
</Layout>
102+
<Separator size={32} />
103+
<Layout padding={false}>
104+
<Card.VeesList isEditable={false} items={exercises} />
105+
</Layout>
106+
</main>
107+
</>
108+
);
109+
};
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import { ClientRender } from './client';
2+
3+
interface IVeesPost {
4+
params: Promise<{ id: string }>
5+
}
6+
7+
const VeesPost = async ({ params }: IVeesPost) => {
8+
const id = (await params).id;
9+
10+
return <ClientRender id={id} />;
11+
};
12+
13+
export default VeesPost;

src/app/initial-provider.tsx

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,27 @@
22

33
import { useEffect } from 'react';
44

5-
import { useVeesActive } from '@/entities/vees';
5+
import { useTimer } from '@/features/Timer/client';
6+
7+
import { useVeesActive } from '@/entities/vees-active';
68

79
interface IInitialProvider {
810
children: React.ReactNode
911
}
1012

1113
export const InitialProvider = ({ children }: IInitialProvider) => {
1214
const { loadVeesActive } = useVeesActive();
15+
const { initializeAudio, resetTimer } = useTimer();
1316

1417
useEffect(() => {
1518
loadVeesActive();
1619
}, []);
1720

21+
useEffect(() => {
22+
initializeAudio();
23+
24+
return () => resetTimer();
25+
}, []);
26+
1827
return children;
1928
};

src/app/vees/client/index.tsx

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,26 @@
11
'use client';
22

3+
import { redirect } from 'next/navigation';
4+
35
import { Card } from '@/widgets/Card';
46

5-
import { PaperOutlineIcon, StopwatchOutlineIcon } from '@/shared/icons';
7+
import { AppRoutes } from '@/shared/constants';
8+
import { FinishOutlineIcon, PaperOutlineIcon, StopwatchOutlineIcon } from '@/shared/icons';
69
import { getDateInfo, getDateRangeDuration } from '@/shared/lib/date';
710
import { Alert, Button, Chip, Empty, Layout, List, Separator, Skeleton } from '@/shared/ui';
811
import { InfoBlock } from '@/shared/ui/client';
912

10-
import { useVeesActive } from '@/entities/vees';
13+
import { useVeesActive } from '@/entities/vees-active';
14+
15+
import styles from './index.module.scss';
1116

1217
export const ClientRender = () => {
13-
const { dataVeesActive, errorVeesActive, loadingVeesActive } = useVeesActive();
18+
const {
19+
completeWithSave,
20+
dataVeesActive,
21+
errorVeesActive,
22+
loadingVeesActive,
23+
} = useVeesActive();
1424

1525
if (loadingVeesActive) {
1626
return (
@@ -92,6 +102,18 @@ export const ClientRender = () => {
92102
<Separator size={32} />
93103
<Layout padding={false}>
94104
<Card.VeesList items={exercises} />
105+
<Separator size={32} />
106+
<Button
107+
className={styles.button}
108+
icon={<FinishOutlineIcon height={22} width={22} />}
109+
onClick={() => {
110+
completeWithSave();
111+
redirect(AppRoutes.MAIN);
112+
}}
113+
variant="none"
114+
>
115+
Завершить и сохранить
116+
</Button>
95117
</Layout>
96118
</>
97119
);

src/entities/vees-active/api/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export * from './get-vees-active';
2+
export * from './remove-vees-active';
3+
export * from './save-vees-active';
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import type { IVeesDto, IVeesListResponse } from '@/shared/types';
2+
3+
import { saveVeesActiveRequest } from '@/persist-storage/save-vees-active.request';
4+
5+
export const saveVeesActive = async (
6+
payload: Omit<IVeesDto, 'id'>,
7+
): Promise<IVeesListResponse[] | null> => (
8+
// POST /vees/save-active
9+
await saveVeesActiveRequest(payload)
10+
);

src/entities/vees-active/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { useVeesActive } from './store';

0 commit comments

Comments
 (0)