Skip to content

Commit edb1a0f

Browse files
committed
advancing calender functionality
1 parent c4ba4bf commit edb1a0f

File tree

1 file changed

+164
-70
lines changed

1 file changed

+164
-70
lines changed

src/components/Calendar.tsx

Lines changed: 164 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,12 @@ import { ADD_EVENT, GET_EVENTS } from '../Mutations/event';
1313
import moment from 'moment';
1414
/* istanbul ignore next */
1515

16+
type Trainee = {
17+
id: number;
18+
name: string;
19+
role: 'admin' | 'manager' | 'trainee';
20+
};
21+
1622
const Calendar = () => {
1723
useDocumentTitle('Calendar');
1824
const [addEventModel, setAddEventModel] = useState(false);
@@ -27,6 +33,21 @@ const Calendar = () => {
2733
const [data, setData] = useState<EventInput[]>([]);
2834
const [getEvents] = useLazyQuery(GET_EVENTS);
2935
const [createEvent] = useMutation(ADD_EVENT);
36+
const [showTraineeDropdown, setShowTraineeDropdown] = useState(false);
37+
const [trainees, setTrainees] = useState<Trainee[]>([
38+
{ id: 1, name: 'John Doe', role: 'admin' },
39+
{ id: 2, name: 'Jane Smith', role: 'manager' },
40+
{ id: 3, name: 'Bob Johnson', role: 'trainee' },
41+
{ id: 4, name: 'Alice Brown', role: 'trainee' },
42+
{ id: 5, name: 'Charlie Green', role: 'manager' },
43+
{ id: 6, name: 'Diana White', role: 'trainee' },
44+
{ id: 7, name: 'Ethan Black', role: 'admin' },
45+
{ id: 8, name: 'Fiona Blue', role: 'manager' },
46+
{ id: 9, name: 'George Gray', role: 'trainee' },
47+
{ id: 10, name: 'Hannah Purple', role: 'trainee' },
48+
]);
49+
const [selectedTrainees, setSelectedTrainees] = useState<number[]>([]);
50+
3051
useEffect(() => {
3152
const fetchData = async () => {
3253
/* istanbul ignore next */
@@ -52,26 +73,24 @@ const Calendar = () => {
5273
};
5374
fetchData();
5475
}, []);
76+
5577
const { t } = useTranslation();
56-
const renderEvent =
57-
/* istanbul ignore next */
5878

59-
(e: EventContentArg) => (
60-
/* istanbul ignore next */
61-
<div
62-
data-html={true}
63-
data-tip={`<div>${e.event.title}<br> ${e.event.extendedProps.hostName} <br> ${e.event.extendedProps.timeToStart} - ${e.event.extendedProps.timeToFinish}</div> `}
64-
className="bg-primary text-white max-w-full min-w-full overflow-auto text-xs md:text-sm"
65-
>
66-
<p className="px-3 py-1 ">{e.event.title}</p>
67-
<p className="px-3 py-1 ">{e.event.extendedProps.hostName}</p>
68-
<p className="px-3 py-1 ">
69-
{e.event.extendedProps.timeToStart} -{' '}
70-
{e.event.extendedProps.timeToFinish}
71-
</p>
72-
<ReactTooltip data-html={true} />
73-
</div>
74-
);
79+
const renderEvent = (e: EventContentArg) => (
80+
<div
81+
data-html={true}
82+
data-tip={`<div>${e.event.title}<br> ${e.event.extendedProps.hostName} <br> ${e.event.extendedProps.timeToStart} - ${e.event.extendedProps.timeToFinish}</div> `}
83+
className="bg-primary text-white max-w-full min-w-full overflow-auto text-xs md:text-sm"
84+
>
85+
<p className="px-3 py-1 ">{e.event.title}</p>
86+
<p className="px-3 py-1 ">{e.event.extendedProps.hostName}</p>
87+
<p className="px-3 py-1 ">
88+
{e.event.extendedProps.timeToStart} -{' '}
89+
{e.event.extendedProps.timeToFinish}
90+
</p>
91+
<ReactTooltip data-html={true} />
92+
</div>
93+
);
7594

7695
const removeModel = (e: any) => {
7796
e.preventDefault();
@@ -83,7 +102,6 @@ const Calendar = () => {
83102
const newState = !addEventModel;
84103
setAddEventModel(newState);
85104
};
86-
/* istanbul ignore next */
87105

88106
const handleAddEvent = (e: any) => {
89107
e.preventDefault();
@@ -104,12 +122,33 @@ const Calendar = () => {
104122
}, 1000);
105123
};
106124

125+
const handleAddGuest = (traineeId: number) => {
126+
setSelectedTrainees((prev) =>
127+
prev.includes(traineeId)
128+
? prev.filter((id) => id !== traineeId)
129+
: [...prev, traineeId],
130+
);
131+
};
132+
133+
const getRoleClass = (role: Trainee['role']) => {
134+
switch (role) {
135+
case 'admin':
136+
return 'bg-red-500';
137+
case 'manager':
138+
return 'bg-yellow-500';
139+
case 'trainee':
140+
return 'bg-green-500';
141+
default:
142+
return 'bg-gray-500';
143+
}
144+
};
145+
107146
return (
108147
<>
109-
{/* =========================== Start:: RegisterTraineeModel =========================== */}
110148
<div
111-
className={`font-serif h-screen w-screen bg-black bg-opacity-30 backdrop-blur-sm fixed top-0 left-0 z-20 flex items-center justify-center px-4 ${addEventModel === true ? 'block' : 'hidden'
112-
}`}
149+
className={`font-serif h-screen w-screen bg-black bg-opacity-30 backdrop-blur-sm fixed top-0 left-0 z-20 flex items-center justify-center px-4 ${
150+
addEventModel === true ? 'block' : 'hidden'
151+
}`}
113152
>
114153
<div className="bg-indigo-100 dark:bg-dark-bg w-full sm:w-3/4 md:w-1/2 xl:w-4/12 rounded-lg p-4 pb-8">
115154
<div className="card-title w-full flex flex-wrap justify-center items-center ">
@@ -119,14 +158,10 @@ const Calendar = () => {
119158
<hr className=" bg-primary border-gray-300 my-3 w-full" />
120159
</div>
121160
<div className="card-body">
122-
{/* istanbul ignore next */}
123161
<form
124162
data-testid="handleAddEvent"
125-
className=" py-3 px-8"
126-
onSubmit /* istanbul ignore next */={(e) =>
127-
/* istanbul ignore next */
128-
handleAddEvent(e)
129-
}
163+
className=" py-3 px-8 overflow-y-auto h-full "
164+
onSubmit={(e) => handleAddEvent(e)}
130165
>
131166
<div className="input my-3 h-9 ">
132167
<div className="grouped-input flex items-center h-full w-full rounded-md">
@@ -137,7 +172,6 @@ const Calendar = () => {
137172
className=" dark:bg-dark-tertiary border dark:text-white border-primary rounded outline-none px-5 font-sans text-xs py-2 w-full"
138173
placeholder={t('Event title')}
139174
value={newEvent.title}
140-
// eslint-disable-next-line prettier/prettier
141175
onChange={(e) =>
142176
setNewEvent({ ...newEvent, title: e.target.value })
143177
}
@@ -153,11 +187,11 @@ const Calendar = () => {
153187
className=" dark:bg-dark-tertiary dark:text-white border border-primary rounded outline-none px-5 font-sans text-xs py-2 w-full"
154188
placeholder={t('Host name')}
155189
value={newEvent.hostName}
156-
onChange /* istanbul ignore next */={(e) =>
157-
/* istanbul ignore next */ setNewEvent({
158-
...newEvent,
159-
hostName: e.target.value,
160-
})
190+
onChange={(e) =>
191+
setNewEvent({
192+
...newEvent,
193+
hostName: e.target.value,
194+
})
161195
}
162196
/>
163197
</div>
@@ -170,11 +204,11 @@ const Calendar = () => {
170204
placeholderText={t('Start Date')}
171205
style={{ marginRight: '10px' }}
172206
selected={newEvent.start}
173-
onChange /* istanbul ignore next */={(start: any) =>
174-
/* istanbul ignore next */ setNewEvent({
175-
...newEvent,
176-
start,
177-
})
207+
onChange={(start: any) =>
208+
setNewEvent({
209+
...newEvent,
210+
start,
211+
})
178212
}
179213
/>
180214
</div>
@@ -187,43 +221,104 @@ const Calendar = () => {
187221
placeholderText={t('End Date')}
188222
style={{ marginRight: '10px' }}
189223
selected={newEvent.end}
190-
onChange=/* istanbul ignore next */ {(end: any) =>
191-
/* istanbul ignore next */
192-
setNewEvent({ ...newEvent, end })
193-
}
224+
onChange={(end: any) => setNewEvent({ ...newEvent, end })}
194225
/>
195226
</div>
196227
</div>
197228

198-
<div className="input my-3 h-9 ">
199-
<div className="grouped-input flex items-center h-full w-full rounded-md">
200-
<input
201-
type="time"
202-
name="hostName"
203-
className="dark:bg-dark-tertiary dark:text-white border border-primary rounded outline-none px-5 font-sans text-xs py-2 w-full"
204-
placeholder={t('Start time')}
205-
value={newEvent.timeToStart}
206-
onChange /* istanbul ignore next */={(e) =>
207-
/* istanbul ignore next */
208-
setNewEvent({ ...newEvent, timeToStart: e.target.value })
209-
}
210-
/>
229+
<div className="input my-3">
230+
<div className="flex space-x-2">
231+
<div className="w-1/2">
232+
<input
233+
type="time"
234+
name="startTime"
235+
className="dark:bg-dark-tertiary dark:text-white border border-primary rounded outline-none px-3 font-sans text-xs py-2 w-full"
236+
placeholder={t('Start time')}
237+
value={newEvent.timeToStart}
238+
onChange={(e) =>
239+
setNewEvent({
240+
...newEvent,
241+
timeToStart: e.target.value,
242+
})
243+
}
244+
/>
245+
</div>
246+
<div className="w-1/2">
247+
<input
248+
type="time"
249+
name="endTime"
250+
className="dark:bg-dark-tertiary dark:text-white border border-primary rounded outline-none px-3 font-sans text-xs py-2 w-full"
251+
placeholder={t('End time')}
252+
value={newEvent.timeToFinish}
253+
onChange={(e) =>
254+
setNewEvent({
255+
...newEvent,
256+
timeToFinish: e.target.value,
257+
})
258+
}
259+
/>
260+
</div>
211261
</div>
212262
</div>
213263

214-
<div className="input my-3 h-9 ">
215-
<div className="grouped-input flex items-center h-full w-full rounded-md">
216-
<input
217-
type="time"
218-
name="hostName"
219-
className="dark:bg-dark-tertiary dark:text-white border border-primary rounded outline-none px-5 font-sans text-xs py-2 w-full"
220-
placeholder={t('End time')}
221-
value={newEvent.timeToFinish}
222-
onChange=/* istanbul ignore next */ {(e) =>
223-
/* istanbul ignore next */
224-
setNewEvent({ ...newEvent, timeToFinish: e.target.value })
225-
}
226-
/>
264+
<div className="input my-3">
265+
<div className="flex items-center justify-between">
266+
<span className="text-sm mb-2">{t('Add guests')}</span>
267+
<button
268+
type="button"
269+
className="bg-primary text-white rounded-full w-6 h-6 flex items-center justify-center mb-2"
270+
onClick={() => setShowTraineeDropdown(!showTraineeDropdown)}
271+
>
272+
{showTraineeDropdown ? '-' : '+'}
273+
</button>
274+
</div>
275+
{showTraineeDropdown && (
276+
<div className="dark:bg-dark-tertiary dark:text-white mt-2 p-2 border border-primary rounded-md h-40 overflow-y-auto">
277+
{trainees.map((trainee) => (
278+
<div key={trainee.id} className="flex items-center mb-2">
279+
<input
280+
type="checkbox"
281+
id={`trainee-${trainee.id}`}
282+
checked={selectedTrainees.includes(trainee.id)}
283+
onChange={() => handleAddGuest(trainee.id)}
284+
className="mr-2"
285+
/>
286+
<label
287+
htmlFor={`trainee-${trainee.id}`}
288+
className="flex items-center"
289+
>
290+
<span
291+
className={`w-2 h-2 rounded-full ${getRoleClass(
292+
trainee.role,
293+
)} mr-2`}
294+
></span>
295+
{trainee.name} ({trainee.role})
296+
</label>
297+
</div>
298+
))}
299+
</div>
300+
)}
301+
<div className="dark:bg-dark-tertiary dark:text-white mt-2 p-2 border border-primary rounded-md min-h-[40px] ">
302+
{selectedTrainees.map((id) => {
303+
const trainee = trainees.find((t) => t.id === id);
304+
if (!trainee) return null;
305+
return (
306+
<span
307+
key={id}
308+
className={`inline-block ${getRoleClass(
309+
trainee.role,
310+
)} text-white rounded-full px-2 py-1 text-xs mr-2 mb-2 relative`}
311+
>
312+
{trainee.name} ({trainee.role})
313+
<button
314+
onClick={() => handleAddGuest(id)}
315+
className="absolute -top-1 -right-1 bg-red-500 text-white rounded-full w-4 h-4 flex items-center justify-center text-xs hover:bg-red-600 text-center font-extrabold"
316+
>
317+
×
318+
</button>
319+
</span>
320+
);
321+
})}
227322
</div>
228323
</div>
229324

@@ -243,7 +338,6 @@ const Calendar = () => {
243338
</div>
244339
</div>
245340
</div>
246-
{/* =========================== End:: RegisterTraineeModel =============================== */}
247341

248342
<div className="px-4 pb-20 w-full dark:bg-dark-frame-bg dark:text-white h-full overflow-y-scroll font-serif">
249343
<div className="w-full flex justify-center text-xl md:text-4xl dark:text-primary mb-10">

0 commit comments

Comments
 (0)