From 8854b495fc8e20b31ea0b092c97bfbacdf747c36 Mon Sep 17 00:00:00 2001 From: AlexandroBolfa Date: Tue, 21 May 2024 14:20:07 +0200 Subject: [PATCH 01/69] Events and tasks visible in the calendar --- .../calendar/components/event/EventForm.tsx | 65 ++++++++++++++----- .../components/event/EventOverview.tsx | 59 ++++++++++------- .../calendar/components/task/TaskForm.tsx | 2 +- src/features/calendar/types/index.ts | 64 +++++++++++------- src/pages/Calendar.css | 6 ++ src/pages/Calendar.tsx | 63 ++++++++++++++++-- 6 files changed, 184 insertions(+), 75 deletions(-) diff --git a/src/features/calendar/components/event/EventForm.tsx b/src/features/calendar/components/event/EventForm.tsx index f7b0e57..ff3409f 100644 --- a/src/features/calendar/components/event/EventForm.tsx +++ b/src/features/calendar/components/event/EventForm.tsx @@ -34,8 +34,10 @@ export const EventForm: React.FC = ({ selectedEvent , mode}) => const [dateError, setDateError] = useState(""); const [timeError, setTimeError] = useState(""); const [description, setDescription] = useState(""); - const [deadlineDate, setDeadlineDate] = React.useState(null); - const [deadlineTime, setDeadlineTime] = React.useState(null); + const [startingDate, setStartingDate] = React.useState(null); + const [startingTime, setStartingTime] = React.useState(null); + const [endingDate, setEndingDate] = React.useState(null); + const [endingTime, setEndingTime] = React.useState(null); const [name, setName] = useState(""); const [status, setStatus] = useState<{ id: number; name: string }>({ id: 1, @@ -66,10 +68,16 @@ export const EventForm: React.FC = ({ selectedEvent , mode}) => if (!name.trim() && selectedEvent===null) { setNameError("Please enter a name"); valid = false; - } if (!deadlineDate && selectedEvent===null) { + } if (!startingDate && selectedEvent===null) { setDateError("Select date"); valid = false; - } if (!deadlineTime && selectedEvent===null) { + } if (!startingTime && selectedEvent===null) { + setTimeError("Select time"); + valid = false; + } if (!endingDate && selectedEvent===null) { + setDateError("Select date"); + valid = false; + } if (!endingTime && selectedEvent===null) { setTimeError("Select time"); valid = false; } @@ -82,8 +90,10 @@ export const EventForm: React.FC = ({ selectedEvent , mode}) => const eventSubmitted:EventProps = { name: name || selectedEvent?.name || "", description: description || selectedEvent?.description, // Use selectedEvent data if description is not entered - deadlineDate: deadlineDate || selectedEvent?.deadlineDate || dayjs(), // Use selectedEvent data or current date if deadlineDate is not entered - deadlineTime: deadlineTime || selectedEvent?.deadlineTime || dayjs(), // Use selectedEvent data or current time if deadlineTime is not entered + startingDate: startingDate || selectedEvent?.startingDate || dayjs(), // Use selectedEvent data or current date if startingDate is not entered + startingTime: startingTime || selectedEvent?.startingTime || dayjs(), // Use selectedEvent data or current time if startingTime is not entered + endingDate: endingDate || selectedEvent?.endingDate || dayjs(), // Use selectedEvent data or current date if endingDate is not entered + endingTime: endingTime || selectedEvent?.endingTime || dayjs(), // Use selectedEvent data or current time if endingTime is not entered status: status || selectedEvent?.status, categories: categories || selectedEvent?.categories || [], }; @@ -91,16 +101,20 @@ export const EventForm: React.FC = ({ selectedEvent , mode}) => console.log(eventSubmitted); dummyDataForEvents.push(eventSubmitted); setName(""); - setDeadlineTime(null); - setDeadlineDate(null); + setStartingTime(null); + setStartingDate(null); + setEndingTime(null); + setEndingDate(null); setDescription(""); setStatus({ id: 1, name: "Not started" }) } }; useEffect(() => {setNameError(""); setTimeError(""); setDateError(""); setName(selectedEvent?.name||name) - setDeadlineDate(dayjs(selectedEvent?.deadlineDate)||deadlineDate) - setDeadlineTime(dayjs(selectedEvent?.deadlineTime)||deadlineTime) + setStartingDate(dayjs(selectedEvent?.startingDate)||startingDate) + setStartingTime(dayjs(selectedEvent?.startingTime)||startingTime) + setEndingDate(dayjs(selectedEvent?.endingDate)||endingDate) + setEndingTime(dayjs(selectedEvent?.endingTime)||endingTime) setDescription(selectedEvent?.description||description) setCategories(selectedEvent?.categories||categories); let nameValue = selectedEvent?.name || ""; @@ -166,15 +180,29 @@ export const EventForm: React.FC = ({ selectedEvent , mode}) =>
- setDeadlineDate(newValue)} views={["year", "month", "day"]}/> + setStartingDate(newValue)} + views={["year", "month", "day"]}/> + {dateError && {dateError}} +
+
+ setStartingTime(newValue)}/> + {timeError && {timeError}} +
+
+ setEndingDate(newValue)} + views={["year", "month", "day"]}/> {dateError && {dateError}}
- setDeadlineTime(newValue)} /> + setEndingTime(newValue)}/> {timeError && {timeError}}
@@ -193,8 +221,9 @@ export const EventForm: React.FC = ({ selectedEvent , mode}) => /> ))} - {mode === "create" && ( + + )} + + ); +}; + +export default Contact; diff --git a/src/features/contacts/components/ContactsList.tsx b/src/features/contacts/components/ContactsList.tsx index 67e7683..0573b5e 100644 --- a/src/features/contacts/components/ContactsList.tsx +++ b/src/features/contacts/components/ContactsList.tsx @@ -1,6 +1,105 @@ -const ContactsList = () => { - return ( - <> - ) +import Heading from "../../../components/Elements/Headings/Heading"; +import { ContactPropsResponse, ContactsPropsResponse } from "../types"; +import PaginationRounded from "../../../components/Elements/Pagination/pagination"; +import { useEffect, useState } from "react"; +import Contact from "./Contact"; +import { deleteContact, getAllContactsByUserId } from "../api/contactApi"; +import SpinnerComponent from "../../spinner/SpinnerComponent"; + +interface ContactsListProps { + change: boolean; } -export default ContactsList \ No newline at end of file + +const ContactsList: React.FC = ({ change }) => { + const [currentPage, setCurrentPage] = useState(1); + const handleChangeOfPage = ( + event: React.ChangeEvent, + value: number + ) => { + setCurrentPage(value); + }; + const contactsPerPage = 5; + + const [contacts, setContacts] = useState([]); + const userId = "f656d97d-63b7-451a-91ee-0e620e652c9e"; + + const [loading, setLoading] = useState(false); + const [error, setError] = useState(null); + + const setAllContacts = (response: ContactsPropsResponse) => { + setContacts(response.contacts); + console.log("Contacts", contacts); + }; + + useEffect(() => { + const fetchContacts = async () => { + setLoading(true); + setError(null); + try { + const response = await getAllContactsByUserId(userId); + // const response = await getDummyContacts(); + await setAllContacts(response); + console.log("Response", response); + } catch (error) { + console.error("Failed to fetch contacts:", error); + setError("Failed to fetch contacts. Please try again later."); + } finally { + setLoading(false); + } + }; + + fetchContacts().then((r) => console.log("Contacts fetched")); + }, [change]); + + const handleDeleteContact = (contactToDelete: ContactPropsResponse) => { + deleteContact(contactToDelete.id) + .then(async () => { + const response = getAllContactsByUserId(userId); + await setAllContacts(await response); + console.log("Response", response); + }) + .catch((error) => { + console.error("Failed to delete alarm:", error); + }); + }; + + return ( + <> + + {loading ? ( + + ) : error ? ( + + ) : ( + <> + {contacts.length === 0 ? ( + + ) : ( + <> + {contacts.map((contact, index) => ( + handleDeleteContact(contact)} + /> + ))} + + {/* Conditionally render pagination only when there are 5 or more contacts*/} + {contacts.length > contactsPerPage && ( // Display pagination only if there are more than 5 alarms + + )} + + )} + + )} + + ); +}; +export default ContactsList; diff --git a/src/features/contacts/types/index.ts b/src/features/contacts/types/index.ts index f0f85a9..9f9113e 100644 --- a/src/features/contacts/types/index.ts +++ b/src/features/contacts/types/index.ts @@ -1,4 +1,37 @@ export interface ContactProps { email: string; - imageSrc: string + imageSrc: string; + onDelete?: () => void; + index?: number; +} + + +export interface ContactPropsResponse { + id: string; + email: string; + imageSrc: string; +} + + +export interface ContactsPropsResponse { + contacts: ContactPropsResponse[] +} + + +export const dummyContacts: ContactPropsResponse[] = [ + { + id: "1", + email: "john@example.com", + imageSrc: "https://example.com/john.jpg", + }, + { + id: "2", + email: "jane@example.com", + imageSrc: "https://example.com/jane.jpg", + } +] + + +export function getDummyContacts(): ContactsPropsResponse { + return { contacts: dummyContacts }; } \ No newline at end of file diff --git a/src/pages/Contacts.tsx b/src/pages/Contacts.tsx index fba0532..222938c 100644 --- a/src/pages/Contacts.tsx +++ b/src/pages/Contacts.tsx @@ -1,186 +1,72 @@ -import Heading from "../components/Elements/Headings/Heading"; import { ContentInnerContainer } from "../components/Layout/ContentInnerContainer"; import { ContentLayout } from "../components/Layout/ContentLayout"; -import PaginationRounded from "../components/Elements/Pagination/pagination"; -import InputField from "../components/Form/InputField"; -import Button from "../components/Elements/Button"; import { useState } from "react"; -import * as z from "zod"; -import { XMarkIcon } from "@heroicons/react/24/outline"; import PopUp from "../components/Elements/PopUp/PopUp"; import { ContactProps } from "../features/contacts/types"; -import * as React from "react"; +import ContactsList from "../features/contacts/components/ContactsList"; +import AddContact from "../features/contacts/components/AddContact"; -const schema = z.object({ - email: z - .string() - .min(1, "Email is required") - .email("Invalid email format. Please insert valid email."), -}); export const Contacts = () => { + const [change, setChange] = useState(false); + const [message, setMessage] = useState(""); const [errors, setErrors] = useState<{ [key: string]: string }>({}); const [email, setEmail] = useState(""); - - const [currentPage, setCurrentPage] = useState(1); - const handleChangeOfPage = (event: React.ChangeEvent, value: number) => { - setCurrentPage(value); - }; - const [contacts, setContacts] = useState< - Array - >([]); - const [selectedContact, setSelectedContact] = useState({ - email: "", - imageSrc: "", - }) + const [contacts, setContacts] = useState>([]); + const [selectedContact, setSelectedContact] = useState( + null + ); const [isHovered, setIsHovered] = useState(false); const [showPopUp, setShowPopUp] = useState(false); const [popupType, setPopupType] = useState<"success" | "delete" | null>(null); - const handleAddContact = () => { - setMessage(""); - setErrors({}); - - try { - schema.parse({ email }); - console.log({ email }); - - //logic to add the contacts to the list - setContacts([ - ...contacts, - { - email, - imageSrc: - "https://yt3.googleusercontent.com/wzEypbVsmY9BI-IbLwVius4UvC2rejtJB_PTXAdPpYXQ07EIjl5Ms55NCFq_dILwONpxrzE2xA=s900-c-k-c0x00ffffff-no-rj", - }, - ]); - setEmail(""); - handleSuccessPopup(); - } catch (error) { - if (error instanceof z.ZodError) { - const fieldErrors: { [key: string]: string } = {}; - error.errors.forEach((err) => { - const path = err.path.join("."); - fieldErrors[path] = err.message; - }); - setErrors(fieldErrors); - } - } - }; - - const handleChange = (e: React.ChangeEvent) => { - setEmail(e.target.value); - setErrors({ ...errors, email: "" }); - setMessage(""); - }; - - const handleDeleteContact = (index: number) => { - // Set the selected contact - setSelectedContact(contacts[index]); - // Show the delete popup - handleDeletePopup(); - - }; - // Function to handle the deletion process - const handleConfirmDelete = () => { - - const updatedContacts = [...contacts]; - updatedContacts.splice( - updatedContacts.findIndex((contact) => contact.email === selectedContact.email), - 1 - ); - setContacts(updatedContacts); - setShowPopUp(false); - - }; + // const handleDeleteContact = (index: number) => { + // setSelectedContact(contacts[index]); + // handleDeletePopup(); + // }; + // // Function to handle the deletion process + // const handleConfirmDelete = () => { + // const updatedContacts = [...contacts]; + // updatedContacts.splice( + // updatedContacts.findIndex( + // (contact) => contact.email === selectedContact.email + // ), + // 1 + // ); + // setContacts(updatedContacts); + // setShowPopUp(false); + // }; const handleSuccessPopup = () => { setPopupType("success"); setShowPopUp(true); }; - + const handleDeletePopup = () => { setPopupType("delete"); setShowPopUp(true); }; - return ( <> - - {contacts.length === 0 ? ( - - ) : ( - <> - {contacts.map((contact, index) => ( -
setIsHovered(index)} - onMouseLeave={() => setIsHovered(false)} - > -
- {contact.email} -
-
- -
- - {/* ensures that the XMark icon appears only on the contact you're hovering over. */} - {isHovered === index && ( -
- -
- )} -
- ))} - - {/* Conditionally render pagination only when there are 5 or more contacts*/} - {contacts.length >= 8 && ( - - )} - - - )} +
- - - - -