esercizio

This commit is contained in:
Dmitri 2025-11-16 18:21:14 +01:00
parent 14ffafe801
commit 77758f2c29
Signed by: kanopo
GPG Key ID: 759ADD40E3132AC7
6 changed files with 226 additions and 11 deletions

40
package-lock.json generated
View File

@ -8,6 +8,7 @@
"name": "better-tictactoe-front-end",
"version": "0.1.0",
"dependencies": {
"@tanstack/react-query": "^5.90.9",
"@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
@ -3399,6 +3400,32 @@
"url": "https://github.com/sponsors/gregberge"
}
},
"node_modules/@tanstack/query-core": {
"version": "5.90.9",
"resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.90.9.tgz",
"integrity": "sha512-UFOCQzi6pRGeVTVlPNwNdnAvT35zugcIydqjvFUzG62dvz2iVjElmNp/hJkUoM5eqbUPfSU/GJIr/wbvD8bTUw==",
"license": "MIT",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/tannerlinsley"
}
},
"node_modules/@tanstack/react-query": {
"version": "5.90.9",
"resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.90.9.tgz",
"integrity": "sha512-Zke2AaXiaSfnG8jqPZR52m8SsclKT2d9//AgE/QIzyNvbpj/Q2ln+FsZjb1j69bJZUouBvX2tg9PHirkTm8arw==",
"license": "MIT",
"dependencies": {
"@tanstack/query-core": "5.90.9"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/tannerlinsley"
},
"peerDependencies": {
"react": "^18 || ^19"
}
},
"node_modules/@testing-library/dom": {
"version": "8.19.0",
"resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-8.19.0.tgz",
@ -19048,6 +19075,19 @@
"loader-utils": "^2.0.0"
}
},
"@tanstack/query-core": {
"version": "5.90.9",
"resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.90.9.tgz",
"integrity": "sha512-UFOCQzi6pRGeVTVlPNwNdnAvT35zugcIydqjvFUzG62dvz2iVjElmNp/hJkUoM5eqbUPfSU/GJIr/wbvD8bTUw=="
},
"@tanstack/react-query": {
"version": "5.90.9",
"resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.90.9.tgz",
"integrity": "sha512-Zke2AaXiaSfnG8jqPZR52m8SsclKT2d9//AgE/QIzyNvbpj/Q2ln+FsZjb1j69bJZUouBvX2tg9PHirkTm8arw==",
"requires": {
"@tanstack/query-core": "5.90.9"
}
},
"@testing-library/dom": {
"version": "8.19.0",
"resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-8.19.0.tgz",

View File

@ -3,6 +3,7 @@
"version": "0.1.0",
"private": true,
"dependencies": {
"@tanstack/react-query": "^5.90.9",
"@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",

View File

@ -1,4 +1,5 @@
import { Routes, Route, Outlet, Link } from "react-router-dom";
import CheckAgeForm from "./pages/CheckAgeForm";
import { CheckName } from './pages/CheckName';
import { Home } from './pages/Home';
@ -8,6 +9,7 @@ export default function App() {
<Route path="/" element={<Layout />}>
<Route index element={<Home />} />
<Route path="check-name" element={<CheckName />} />
<Route path="check-age-form" element={<CheckAgeForm />} />
<Route path="*" element={<NoMatch />} />
</Route>
</Routes>
@ -25,6 +27,9 @@ function Layout() {
<li>
<Link to="/check-name">Check Name</Link>
</li>
<li>
<Link to="/check-age-form">Check age form</Link>
</li>
</ul>
</nav>
<hr />

View File

@ -3,11 +3,21 @@ import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import { BrowserRouter } from "react-router-dom";
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
const queryClient = new QueryClient()
const root = ReactDOM.createRoot(
document.getElementById('root') as HTMLElement
);
root.render(<BrowserRouter><App /></BrowserRouter>);
root.render(
<BrowserRouter>
<QueryClientProvider client={queryClient}>
<App />
</QueryClientProvider>
</BrowserRouter>
);
// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))

View File

@ -31,3 +31,12 @@ interface BaseResponseError extends BaseResponseInteface {
}
export type BaseResponse = BaseResponseSuccess | BaseResponseError;
export type FormState = {
name: string
age: number
married?: boolean
dateOfBirth: Date
}

150
src/pages/CheckAgeForm.tsx Normal file
View File

@ -0,0 +1,150 @@
import { useMutation, useQuery } from "@tanstack/react-query";
import { useState } from "react";
import { BaseResponse, FormState } from "../interfaces";
const CheckAgeForm = () => {
const [form, setForm] = useState<FormState>({
name: "",
age: 0,
dateOfBirth: new Date()
})
const validate = useMutation({
mutationFn: async (data: FormState): Promise<BaseResponse> => {
const res = await fetch('http://localhost:3001/info/validate-form', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
...data
})
})
// TODO: usare axios o altre librerie per avere un minimo di typesafety, qui sto pregando che il risultato sia quello che mi aspetto e sinceramente non so se dia errore fino a quando non prova a chiamare un oggetto annidato
const resData: BaseResponse = await res.json()
console.log(resData)
return resData
}
})
const handleSand = async () => {
await validate.mutateAsync({
...form
})
}
const handleReset = () => {
validate.reset()
setForm({
name: "",
age: 0,
dateOfBirth: new Date()
})
}
const isAbove18 = form.age >= 18
if (validate.isError) {
return (
<div>
<h1>ERRORE INVIO DATI</h1>
<button onClick={handleReset}>RIPROVA</button>
</div>
);
}
if (validate.isPending) {
return (
<div>
<h1>INVIO IN CORSO</h1>
<button onClick={handleReset}>ANNULLA</button>
</div>
);
}
if (validate.isSuccess) {
return (
<div>
{validate.data?.success === true && <h1>DATI INVIATI VALIDI</h1>}
{validate.data?.success === false && <h1>DATI INVIATI NON VALIDI</h1>}
<button onClick={handleReset}>INVIA UN ALTRO VALORE</button>
</div>
);
}
return (
<div>
<input
type="text"
placeholder="name"
value={form.name}
onChange={(e) => {
setForm((prev) => {
return {
...prev,
name: e.target.value
}
});
}}
/>
<input
type="number"
placeholder="age"
value={form.age}
onChange={(e) => {
setForm((prev) => {
const age = Number.parseInt(e.target.value) ?? 0
return {
...prev,
age
}
});
}}
/>
{
(isAbove18) && (
<input
type="checkbox"
placeholder="married?"
checked={form.married}
onChange={() => {
setForm((prev) => {
return {
...prev,
married: !(prev.married ?? false)
}
});
}}
/>
)
}
<input
type="date"
placeholder="date of birth"
value={form.dateOfBirth.toISOString().split("T")[0]}
onChange={(e) => {
setForm((prev) => {
const newDate = new Date(e.target.value);
return {
...prev,
dateOfBirth: newDate,
};
});
}}
/>
<button
onClick={handleSand}
>
VALIDA
</button>
</div>
)
}
export default CheckAgeForm