Skip to content

Commit 44d6073

Browse files
Add custom hooks for dashboard components
1 parent 9f32cfc commit 44d6073

File tree

17 files changed

+852
-470
lines changed

17 files changed

+852
-470
lines changed
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
import { Dispatch, SetStateAction, useEffect, useState } from 'react';
2+
import { CookieService, IText, TextService, TextType } from '../../../services';
3+
import { FestivalService, IFestival } from '../../../services/admin/festival';
4+
import { Dayjs } from 'dayjs';
5+
import { SwitchChangeEventHandler } from 'antd/es/switch';
6+
7+
type NoUndefinedRangeValueType<DateType> = [DateType | null, DateType | null] | null;
8+
9+
interface IDashboardHooks {
10+
isTextLoading: boolean
11+
texts: IText[]
12+
infoText: IText
13+
festival: IFestival
14+
setNewTexts: Dispatch<SetStateAction<IText[]>>
15+
setTexts: Dispatch<SetStateAction<IText[]>>
16+
handleFestivalDate: (dates: NoUndefinedRangeValueType<Dayjs> | null, dateStrings: [string, string]) => void
17+
handleFestivalLatitude: (value: number | null) => void
18+
handleFestivalLongitude: (value: number | null) => void
19+
updateInformationsVisibility: SwitchChangeEventHandler
20+
toggleVisibility: (key: string) => (checked: boolean) => void
21+
toggleLoading: { [x: string]: boolean }
22+
}
23+
24+
export const useDashboardHooks = (): IDashboardHooks => {
25+
const [isTextLoading, setIsTextLoading] = useState<boolean>(false);
26+
const [texts, setTexts] = useState<IText[]>([]);
27+
const [newTexts, setNewTexts] = useState<IText[]>(texts);
28+
const [infoText, setInfoText] = useState<IText>({} as IText);
29+
const [festival, setFestival] = useState<IFestival>({} as IFestival);
30+
const [toggleLoading, setToggleLoading] = useState<{ [x: string]: boolean }>({});
31+
32+
const updateInformationsVisibility = (checked: boolean): void => {
33+
if (infoText) {
34+
TextService.update(infoText.id, {
35+
...infoText,
36+
isShowed: checked,
37+
}).then((res) =>
38+
setInfoText({
39+
...infoText,
40+
...res,
41+
})
42+
);
43+
}
44+
};
45+
46+
const handleFestivalDate = (dates: NoUndefinedRangeValueType<Dayjs>): void => {
47+
if (dates) {
48+
if (dates[0] && dates[1]) {
49+
FestivalService.update(festival.id, {
50+
...festival,
51+
startDate: dates[0].toDate(),
52+
endDate: dates[1].toDate(),
53+
}).then((res) =>
54+
setFestival({
55+
...festival,
56+
...res,
57+
})
58+
);
59+
}
60+
}
61+
};
62+
63+
const handleFestivalLatitude = (newLatitude: number | null): void => {
64+
FestivalService.update(festival.id, {
65+
...festival,
66+
location: { ...festival.location, latitude: newLatitude || 0 },
67+
}).then((res) =>
68+
setFestival({
69+
...festival,
70+
...res,
71+
})
72+
);
73+
};
74+
75+
const handleFestivalLongitude = (newLongitude: number | null): void => {
76+
FestivalService.update(festival.id, {
77+
...festival,
78+
location: { ...festival.location, longitude: newLongitude || 0 },
79+
}).then((res) =>
80+
setFestival({
81+
...festival,
82+
...res,
83+
})
84+
);
85+
};
86+
87+
const toggleVisibility =
88+
(key: string) =>
89+
(checked: boolean): void => {
90+
setToggleLoading({ [key]: true });
91+
FestivalService.update(festival.id, {
92+
...festival,
93+
[key]: checked,
94+
})
95+
.then((res) => setFestival({ ...festival, ...res }))
96+
.finally(() => setToggleLoading({ [key]: false }));
97+
};
98+
99+
useEffect(() => {
100+
setIsTextLoading(true);
101+
TextService.getAll()
102+
.then(setTexts)
103+
.finally(() => setIsTextLoading(false));
104+
TextService.getByTextType(TextType.info).then(setInfoText);
105+
FestivalService.getLastFestival().then((festival) => {
106+
CookieService.set(CookieService.festivalId, festival.id);
107+
setFestival(festival);
108+
});
109+
}, [newTexts]);
110+
111+
return {
112+
isTextLoading,
113+
texts,
114+
infoText,
115+
festival,
116+
setNewTexts,
117+
setTexts,
118+
handleFestivalDate,
119+
handleFestivalLatitude,
120+
handleFestivalLongitude,
121+
updateInformationsVisibility,
122+
toggleVisibility,
123+
toggleLoading,
124+
};
125+
};

src/components/Admin/Dashboard/index.tsx

Lines changed: 22 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,8 @@
1-
import dayjs, { Dayjs } from 'dayjs';
1+
import dayjs from 'dayjs';
22
import loadable from '@loadable/component';
3-
import React, { useEffect, useState } from 'react';
3+
import React from 'react';
44

5-
import {
6-
Card,
7-
DatePicker,
8-
InputNumber,
9-
Switch,
10-
Flex,
11-
} from 'antd';
12-
13-
import { CookieService, IText, TextService, TextType } from '../../../services';
14-
import { FestivalService, IFestival } from '../../../services/admin/festival';
5+
import { Card, DatePicker, InputNumber, Switch, Flex, } from 'antd';
156

167
import {
178
DASHBOARD_PLACEHOLDER_LATITUDE,
@@ -24,106 +15,33 @@ import {
2415
DASHBOARD_TITLE_INFORMATION,
2516
} from './Dashboard.constants';
2617
import DashboardText from '../DashboardText';
18+
import { useDashboardHooks } from './Dashboard.hooks';
2719

2820
const Navigation = loadable(() => import('../../../pages/admin/Navigation'));
2921
const { RangePicker } = DatePicker;
3022

31-
type NoUndefinedRangeValueType<DateType> = [DateType | null, DateType | null] | null;
32-
3323
const Dashboard: React.FC = () => {
34-
const [isTextLoading, setIsTextLoading] = useState<boolean>(false);
35-
const [texts, setTexts] = useState<IText[]>([]);
36-
const [newTexts, setNewTexts] = useState<IText[]>(texts);
37-
const [infoText, setInfoText] = useState<IText>({} as IText);
38-
const [festival, setFestival] = useState<IFestival>({} as IFestival);
39-
const [toggleLoading, setToggleLoading] = useState<{ [x: string]: boolean }>({});
40-
41-
useEffect(() => {
42-
setIsTextLoading(true);
43-
TextService.getAll()
44-
.then(setTexts)
45-
.finally(() => setIsTextLoading(false));
46-
TextService.getByTextType(TextType.info).then(setInfoText);
47-
FestivalService.getLastFestival().then((festival) => {
48-
CookieService.set(CookieService.festivalId, festival.id);
49-
setFestival(festival);
50-
});
51-
}, [newTexts]);
52-
53-
const updateInformationsVisibility = (checked: boolean): void => {
54-
if (infoText) {
55-
TextService.update(infoText.id, {
56-
...infoText,
57-
isShowed: checked,
58-
}).then((res) =>
59-
setInfoText({
60-
...infoText,
61-
...res,
62-
})
63-
);
64-
}
65-
};
66-
67-
const handleFestivalDate = (dates: NoUndefinedRangeValueType<Dayjs>): void => {
68-
if (dates) {
69-
if (dates[0] && dates[1]) {
70-
FestivalService.update(festival.id, {
71-
...festival,
72-
startDate: dates[0].toDate(),
73-
endDate: dates[1].toDate(),
74-
}).then((res) =>
75-
setFestival({
76-
...festival,
77-
...res,
78-
})
79-
);
80-
}
81-
}
82-
};
83-
84-
const handleFestivalLatitude = (newLatitude: number | null): void => {
85-
FestivalService.update(festival.id, {
86-
...festival,
87-
location: { ...festival.location, latitude: newLatitude || 0 },
88-
}).then((res) =>
89-
setFestival({
90-
...festival,
91-
...res,
92-
})
93-
);
94-
};
95-
96-
const handleFestivalLongitude = (newLongitude: number | null): void => {
97-
FestivalService.update(festival.id, {
98-
...festival,
99-
location: { ...festival.location, longitude: newLongitude || 0 },
100-
}).then((res) =>
101-
setFestival({
102-
...festival,
103-
...res,
104-
})
105-
);
106-
};
107-
108-
const toggleVisibility =
109-
(key: string) =>
110-
(checked: boolean): void => {
111-
setToggleLoading({ [key]: true });
112-
FestivalService.update(festival.id, {
113-
...festival,
114-
[key]: checked,
115-
})
116-
.then((res) => setFestival({ ...festival, ...res }))
117-
.finally(() => setToggleLoading({ [key]: false }));
118-
};
119-
24+
const {
25+
isTextLoading,
26+
texts,
27+
infoText,
28+
festival,
29+
setNewTexts,
30+
setTexts,
31+
handleFestivalDate,
32+
handleFestivalLatitude,
33+
handleFestivalLongitude,
34+
updateInformationsVisibility,
35+
toggleVisibility,
36+
toggleLoading,
37+
} = useDashboardHooks();
12038
return (
12139
<Navigation>
12240
<div className="grid grid-cols-12 gap-2 md:gap-5">
123-
<Card bordered={false} className="rounded-lg col-span-12 lg:col-span-8">
124-
<DashboardText isLoading={isTextLoading} texts={texts} setTexts={setTexts} setNewTexts={setNewTexts} />
41+
<Card variant="borderless" className="rounded-lg col-span-12 lg:col-span-8">
42+
<DashboardText isLoading={isTextLoading} texts={texts} setTexts={setTexts} setNewTexts={setNewTexts}/>
12543
</Card>
126-
<Card bordered={false} className="rounded-lg col-span-12 lg:col-span-4">
44+
<Card variant="borderless" className="rounded-lg col-span-12 lg:col-span-4">
12745
<div className="space-y-4">
12846
<div className="text-3xl text-center">{DASHBOARD_TITLE_INFORMATION}</div>
12947
<Flex align="baseline" justify="space-between">
@@ -160,7 +78,7 @@ const Dashboard: React.FC = () => {
16078
</Flex>
16179
</Flex>
16280
<Flex align="center" gap="small">
163-
<Switch disabled={!infoText?.id} onChange={updateInformationsVisibility} checked={infoText?.isShowed} />
81+
<Switch disabled={!infoText?.id} onChange={updateInformationsVisibility} checked={infoText?.isShowed}/>
16482
<div>{DASHBOARD_SHOW_HOME_INFORMATION}</div>
16583
</Flex>
16684
<Flex align="center" gap="small">
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
import { Dispatch, SetStateAction, useEffect, useState } from 'react';
2+
import { allEditions, PreviousEdition } from '../../../constants';
3+
import { IMovie, MovieService } from '../../../services';
4+
import { Form, FormInstance, message } from 'antd';
5+
import useModal from '../../../constants/hooks';
6+
import { showErrorFormMessage } from '../../../lib/validation';
7+
8+
interface IDashboardMovieHooks {
9+
isOpen: boolean
10+
previewURL: string
11+
editions: PreviousEdition[]
12+
movies: IMovie[]
13+
addRowModalVisible: boolean
14+
selectedEdition: string
15+
formRowAddition: FormInstance
16+
formRowEdition: FormInstance
17+
isMovieLoading: boolean
18+
setSelectedEdition: Dispatch<SetStateAction<string>>
19+
setEditingId: Dispatch<SetStateAction<number>>
20+
setNewMovies: Dispatch<SetStateAction<IMovie[]>>
21+
setAddRowModalVisible: Dispatch<SetStateAction<boolean>>
22+
isEditing: (record: IMovie) => boolean
23+
openModalPreview: (imageId: string) => void
24+
handleOkModal: () => void
25+
toggle: () => void
26+
}
27+
28+
export const useDashboardMovieHooks = (): IDashboardMovieHooks => {
29+
const editions = allEditions(true);
30+
const [isMovieLoading, setIsMovieLoading] = useState<boolean>(false);
31+
const [movies, setMovies] = useState<IMovie[]>([]);
32+
const [newMovies, setNewMovies] = useState<IMovie[]>([]);
33+
const [selectedEdition, setSelectedEdition] = useState<string>(editions[0].value);
34+
35+
// Row edition
36+
const [editingId, setEditingId] = useState<number>(0);
37+
const [formRowEdition] = Form.useForm();
38+
39+
// Add row modal
40+
const [addRowModalVisible, setAddRowModalVisible] = useState<boolean>(false);
41+
const [formRowAddition] = Form.useForm();
42+
43+
// Preview modal
44+
const { isOpen, toggle } = useModal();
45+
const [previewURL, setPreviewURL] = useState<string>('');
46+
47+
const handleOkModal = () => {
48+
const hideLoadingMessage = message.loading('Ajout en cours', 0);
49+
formRowAddition
50+
.validateFields()
51+
.then((values) => {
52+
MovieService.create(values)
53+
.then((movie) => {
54+
setMovies([...movies, movie]);
55+
message.success('Court-métrage ajouté', 2.5);
56+
})
57+
.catch((err) => message.error(`Erreur lors de l'ajout: ${err}`, 2.5))
58+
.finally(() => {
59+
hideLoadingMessage();
60+
formRowAddition.resetFields();
61+
});
62+
setAddRowModalVisible(false);
63+
})
64+
.catch(() => showErrorFormMessage())
65+
.finally(() => hideLoadingMessage());
66+
};
67+
68+
const openModalPreview = (imageId: string) => {
69+
setPreviewURL(imageId);
70+
toggle();
71+
};
72+
73+
const isEditing = (record: IMovie): boolean => record.id === editingId;
74+
75+
useEffect(() => {
76+
setIsMovieLoading(true);
77+
MovieService.getAll()
78+
.then(setMovies)
79+
.finally(() => setIsMovieLoading(false));
80+
}, [newMovies]);
81+
82+
return {
83+
isOpen,
84+
previewURL,
85+
editions,
86+
movies,
87+
addRowModalVisible,
88+
selectedEdition,
89+
formRowAddition,
90+
formRowEdition,
91+
isMovieLoading,
92+
setSelectedEdition,
93+
setEditingId,
94+
setNewMovies,
95+
setAddRowModalVisible,
96+
isEditing,
97+
openModalPreview,
98+
handleOkModal,
99+
toggle,
100+
};
101+
};

0 commit comments

Comments
 (0)