prettier code

This commit is contained in:
Romulus21
2025-10-31 20:48:27 +01:00
parent a94932059a
commit 76e99f574a
3 changed files with 2870 additions and 2665 deletions

View File

@@ -11,25 +11,25 @@
"generate-pwa-assets": "pwa-assets-generator" "generate-pwa-assets": "pwa-assets-generator"
}, },
"dependencies": { "dependencies": {
"react": "^18.3.1", "react": "^19.0.0",
"react-dom": "^18.3.1" "react-dom": "^19.0.0"
}, },
"devDependencies": { "devDependencies": {
"@types/react": "^18.3.11", "@types/react": "^19.0.0",
"@types/react-dom": "^18.3.0", "@types/react-dom": "^19.0.0",
"@typescript-eslint/eslint-plugin": "^6.21.0", "@typescript-eslint/eslint-plugin": "^8.46.0",
"@typescript-eslint/parser": "^6.21.0", "@typescript-eslint/parser": "^8.46.0",
"@vite-pwa/assets-generator": "^0.2.6", "@vite-pwa/assets-generator": "^1.0.0",
"@vitejs/plugin-react-swc": "^3.7.1", "@vitejs/plugin-react-swc": "^4.2.0",
"autoprefixer": "^10.4.20", "autoprefixer": "^10.4.21",
"eslint": "^8.57.1", "eslint": "^9.0.0",
"eslint-plugin-react-hooks": "^4.6.2", "eslint-plugin-react-hooks": "^7.0.0",
"eslint-plugin-react-refresh": "^0.4.12", "eslint-plugin-react-refresh": "^0.4.24",
"postcss": "^8.4.47", "postcss": "^8.5.6",
"rollup-plugin-copy": "^3.5.0", "rollup-plugin-copy": "^3.5.0",
"tailwindcss": "^3.4.13", "tailwindcss": "^3.4.18",
"typescript": "^5.6.2", "typescript": "^5.9.3",
"vite": "^5.4.8", "vite": "^7.0.0",
"vite-plugin-pwa": "^0.17.5" "vite-plugin-pwa": "^1.1.0"
} }
} }

5108
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,176 +1,251 @@
import {ChangeEvent, FormEvent, useEffect, useState} from "react"; import { ChangeEvent, FormEvent, useEffect, useState } from "react";
import {useLocalStorage} from "./hooks/LocalStorageHooks.ts"; import { useLocalStorage } from "./hooks/LocalStorageHooks.ts";
import {Birthday} from "./types.ts"; import { Birthday } from "./types.ts";
import {arrayRange, pad} from "./utilities.ts"; import { arrayRange, pad } from "./utilities.ts";
import BirthdayList from "./components/BirthdayList.tsx"; import BirthdayList from "./components/BirthdayList.tsx";
import {EditSVG, PlusSVG, TrashSVG} from "./components/SVG.tsx"; import { EditSVG, PlusSVG, TrashSVG } from "./components/SVG.tsx";
import cake from '../public/cake.svg' import cake from "../public/cake.svg";
function App() { function App() {
const emptyAddForm: Birthday = {
id: 0,
name: "",
day: 1,
month: 1,
year: undefined,
birthday: "",
group: null,
};
const [addModal, setAddModal] = useState(false);
const [selectedPerson, setSelectedPerson] = useState<Birthday | null>(null);
const [addForm, setAddForm] = useState(emptyAddForm);
const [birthdays, setBirthdays] = useState<Birthday[]>([]);
const [data, setData] = useLocalStorage("birthdays-app-data", {
birthdays: [],
});
const emptyAddForm: Birthday = {id: 0, name: '', day: 1, month: 1, year: undefined, birthday: '', group: null} useEffect(() => {
const [addModal, setAddModal] = useState(false) setBirthdays(sortPersons(data.birthdays));
const [selectedPerson, setSelectedPerson] = useState<Birthday|null>(null) }, [data, data.birthdays]);
const [addForm, setAddForm] = useState(emptyAddForm)
const [birthdays, setBirthdays] = useState<Birthday[]>([])
const [data, setData] = useLocalStorage('birthdays-app-data', {birthdays: []})
useEffect(() => { const handleAddModal = () => {
setBirthdays(sortPersons(data.birthdays)) if (selectedPerson) {
}, [data, data.birthdays]) setAddForm(selectedPerson);
}
setAddModal(true);
};
const handleCloseModal = () => {
setAddModal(false);
setAddForm({ ...emptyAddForm, year: 0 });
setSelectedPerson(null);
};
const handleAddModal = () => { const sortPersons = (birthdays: Birthday[]) => {
if (selectedPerson) { birthdays = birthdays
setAddForm(selectedPerson) .reduce((result: Birthday[], item: Birthday) => {
const birthday = `${new Date().getFullYear()}-${pad(item.month)}-${pad(item.day)}`;
item.birthday =
new Date().toISOString().split("T")[0] <= birthday
? birthday
: `${new Date().getFullYear() + 1}-${pad(item.month)}-${pad(item.day)}`;
result.push(item);
return result;
}, [])
.sort((a, b) => {
if (b.birthday < a.birthday) return 1;
if (b.birthday > a.birthday) return -1;
return 0;
});
return birthdays;
};
const handleChangeAddForm = (
event: ChangeEvent<HTMLInputElement | HTMLSelectElement>,
) => {
const value =
event.target.nodeName === "SELECT"
? Number(event.target.value)
: event.target.value;
setAddForm({ ...addForm, [event.target.name]: value });
};
const handleSubmitBirthday = (event: FormEvent) => {
event.preventDefault();
try {
if (
(!selectedPerson &&
birthdays.some((person: Birthday) => person.name === addForm.name)) ||
(selectedPerson && selectedPerson.id !== addForm.id)
) {
throw new Error("Une personne enregistré à déjà ce nom");
}
if (selectedPerson) {
const personIndex = data.birthdays.findIndex(
(p: Birthday) => p.id === selectedPerson.id,
);
if (personIndex >= 0) {
const newList = data.birthdays;
newList[personIndex] = addForm;
setData({ ...data, birthdays: newList });
} else {
throw new Error("Une personne non trouvé dans la liste");
} }
setAddModal(true) } else {
} const maxId = data.birthdays.reduce(
const handleCloseModal = () => { (result: number, item: Birthday) => {
setAddModal(false) if (item.id > result) {
setAddForm({...emptyAddForm, year: 0}) result = item.id;
setSelectedPerson(null)
}
const sortPersons = (birthdays: Birthday[]) => {
birthdays = birthdays.reduce((result: Birthday[], item: Birthday) => {
const birthday = `${(new Date()).getFullYear()}-${pad(item.month)}-${pad(item.day)}`
item.birthday = (new Date()).toISOString().split('T')[0] <= birthday ? birthday : `${(new Date()).getFullYear() + 1}-${pad(item.month)}-${pad(item.day)}`
result.push(item)
return result
}, [])
.sort((a, b) => {
if (b.birthday < a.birthday) return 1
if (b.birthday > a.birthday) return -1
return 0
})
return birthdays
}
const handleChangeAddForm = (event: ChangeEvent<HTMLInputElement|HTMLSelectElement>) => {
const value = event.target.nodeName === 'SELECT' ? Number(event.target.value) : event.target.value
setAddForm({...addForm, [event.target.name]: value})
}
const handleSubmitBirthday = (event: FormEvent) => {
event.preventDefault()
try {
if (!selectedPerson && birthdays.some(person => person.name === addForm.name) || (selectedPerson && selectedPerson.id !== addForm.id)) {
throw new Error('Une personne enregistré à déjà ce nom')
} }
if (selectedPerson) { return result;
const personIndex = data.birthdays.findIndex((p: Birthday) => p.id === selectedPerson.id) },
if (personIndex >= 0) { 0,
const newList = data.birthdays );
newList[personIndex] = addForm setData({
setData({...data, birthdays: newList}) ...data,
} else { birthdays: [...data.birthdays, { ...addForm, id: maxId + 1 }],
throw new Error('Une personne non trouvé dans la liste') });
} }
} else { handleCloseModal();
const maxId = data.birthdays.reduce((result: number, item: Birthday) => { } catch (error) {
if (item.id > result) {result = item.id} console.log(error);
return result
}, 0)
setData({...data, birthdays: [...data.birthdays, {...addForm, id: maxId + 1}]})
}
handleCloseModal()
} catch (error) {
console.log(error)
}
} }
};
const selectPerson = (person: Birthday) => setSelectedPerson(person) const selectPerson = (person: Birthday) => setSelectedPerson(person);
const handleDelete = () => { const handleDelete = () => {
console.log(selectedPerson) console.log(selectedPerson);
if (selectedPerson) { if (selectedPerson) {
const personIndex = data.birthdays.findIndex((p: Birthday) => p.id === selectedPerson.id) const personIndex = data.birthdays.findIndex(
if (personIndex >= 0) { (p: Birthday) => p.id === selectedPerson.id,
const newList = data.birthdays );
newList.splice(personIndex, 1) if (personIndex >= 0) {
setData({...data, birthdays: newList}) const newList = data.birthdays;
setSelectedPerson(null) newList.splice(personIndex, 1);
} else { setData({ ...data, birthdays: newList });
throw new Error('Une personne non trouvé dans la liste') setSelectedPerson(null);
} } else {
} throw new Error("Une personne non trouvé dans la liste");
}
} }
};
return ( return (
<> <>
<header className="bg-gray-300 dark:bg-neutral-900 px-5 py-2.5 flex items-center font-bold text-3xl"> <header className="bg-gray-300 dark:bg-neutral-900 px-5 py-2.5 flex items-center font-bold text-3xl">
<img src={cake} alt="birthday cake" className="w-12 inline-block"/> Birthdays <img src={cake} alt="birthday cake" className="w-12 inline-block" />{" "}
</header> Birthdays
</header>
<BirthdayList birthdays={birthdays} selectedPerson={selectedPerson} selectPerson={selectPerson} /> <BirthdayList
birthdays={birthdays}
selectedPerson={selectedPerson}
selectPerson={selectPerson}
/>
<div className="sticky bottom-0 right-0"> <div className="sticky bottom-0 right-0">
<div className="flex flex-row-reverse justify-between p-2 w-full"> <div className="flex flex-row-reverse justify-between p-2 w-full">
{selectedPerson ? <button type="button" {selectedPerson ? (
onClick={handleAddModal} <button
className={`${addModal ? 'translate-x-[100px] h-0' : 'translate-x-0 h-20'} transition bg-blue-700 rounded-full flex justify-center items-center text-white w-20 right-0`}> type="button"
<EditSVG className="w-10" /> onClick={handleAddModal}
</button> className={`${addModal ? "translate-x-[100px] h-0" : "translate-x-0 h-20"} transition bg-blue-700 rounded-full flex justify-center items-center text-white w-20 right-0`}
: <button type="button" >
onClick={handleAddModal} <EditSVG className="w-10" />
className={`${addModal ? 'translate-x-[100px] h-0' : 'translate-x-0 h-20'} transition bg-amber-700 rounded-full flex justify-center items-center text-white w-20 right-0`}> </button>
<PlusSVG className="w-10" /> ) : (
</button>} <button
{selectedPerson && <button type="button" type="button"
onClick={handleDelete} onClick={handleAddModal}
className={`h-20 transition bg-red-500 rounded-full flex justify-center items-center text-white w-20 right-0`}> className={`${addModal ? "translate-x-[100px] h-0" : "translate-x-0 h-20"} transition bg-amber-700 rounded-full flex justify-center items-center text-white w-20 right-0`}
<TrashSVG className="w-10" /> >
</button>} <PlusSVG className="w-10" />
{(selectedPerson || addModal) && <button type="button" </button>
className={`h-10 -mt-5 bg-gray-700 text-white p-2 rounded-full w-10 flex justify-center items-center`} )}
onClick={handleCloseModal}> {selectedPerson && (
<PlusSVG className="w-6 rotate-45" /> <button
</button>} type="button"
</div> onClick={handleDelete}
<form className={`${addModal ? 'h-18' : 'h-0 overflow-hidden'} flex`} className={`h-20 transition bg-red-500 rounded-full flex justify-center items-center text-white w-20 right-0`}
onSubmit={handleSubmitBirthday}> >
<div className="p-2 w-full flex dark:text-neutral-800"> <TrashSVG className="w-10" />
<input name="name" </button>
type="text" )}
autoFocus {(selectedPerson || addModal) && (
placeholder="nom" <button
className="border-2 p-2 flex-1 w-40 h-16 rounded-l-lg" type="button"
value={addForm.name} className={`h-10 -mt-5 bg-gray-700 text-white p-2 rounded-full w-10 flex justify-center items-center`}
onChange={handleChangeAddForm}/> onClick={handleCloseModal}
<select name="day" >
className="px-1" <PlusSVG className="w-6 rotate-45" />
value={addForm.day} </button>
onChange={handleChangeAddForm}> )}
{arrayRange(31, 1).map(day => <option key={'day-' + day} value={day}>{day}</option>)} </div>
</select> <form
<select name="month" className={`${addModal ? "h-18" : "h-0 overflow-hidden"} flex`}
className="px-1" onSubmit={handleSubmitBirthday}
value={addForm.month} >
onChange={handleChangeAddForm}> <div className="p-2 w-full flex dark:text-neutral-800">
{arrayRange(12, 1).map(month => <option key={'month-' + month} <input
value={month}>{month}</option>)} name="name"
</select> type="text"
<select name="year" autoFocus
className="px-1 text-center" placeholder="nom"
value={addForm.year} className="border-2 p-2 flex-1 w-40 h-16 rounded-l-lg"
onChange={handleChangeAddForm}> value={addForm.name}
<option>--</option> onChange={handleChangeAddForm}
{arrayRange(2024, 1900).reverse() />
.map(year => <option key={'year-' + year} <select
value={year}> name="day"
{year} className="px-1"
</option>)} value={addForm.day}
</select> onChange={handleChangeAddForm}
<button type="submit" >
className="bg-green-800 text-white p-2 h-16 rounded-r-lg"> {arrayRange(31, 1).map((day) => (
Valider <option key={"day-" + day} value={day}>
</button> {day}
</div> </option>
</form> ))}
</div> </select>
</> <select
) name="month"
className="px-1"
value={addForm.month}
onChange={handleChangeAddForm}
>
{arrayRange(12, 1).map((month) => (
<option key={"month-" + month} value={month}>
{month}
</option>
))}
</select>
<select
name="year"
className="px-1 text-center"
value={addForm.year}
onChange={handleChangeAddForm}
>
<option>--</option>
{arrayRange(2024, 1900)
.reverse()
.map((year) => (
<option key={"year-" + year} value={year}>
{year}
</option>
))}
</select>
<button
type="submit"
className="bg-green-800 text-white p-2 h-16 rounded-r-lg"
>
Valider
</button>
</div>
</form>
</div>
</>
);
} }
export default App export default App;