esercizio
This commit is contained in:
parent
14ffafe801
commit
77758f2c29
40
package-lock.json
generated
40
package-lock.json
generated
@ -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",
|
||||
|
||||
@ -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",
|
||||
|
||||
19
src/App.tsx
19
src/App.tsx
@ -1,16 +1,18 @@
|
||||
import { Routes, Route, Outlet, Link } from "react-router-dom";
|
||||
import CheckAgeForm from "./pages/CheckAgeForm";
|
||||
import { CheckName } from './pages/CheckName';
|
||||
import { Home } from './pages/Home';
|
||||
|
||||
export default function App() {
|
||||
return (
|
||||
<Routes>
|
||||
<Route path="/" element={<Layout />}>
|
||||
<Route index element={<Home />} />
|
||||
<Route path="check-name" element={<CheckName />} />
|
||||
<Route path="*" element={<NoMatch />} />
|
||||
</Route>
|
||||
</Routes>
|
||||
<Routes>
|
||||
<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 />
|
||||
|
||||
@ -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))
|
||||
|
||||
@ -3,7 +3,7 @@ interface ValidationError {
|
||||
property: string;
|
||||
value?: any;
|
||||
constraints?: {
|
||||
[type: string]: string;
|
||||
[type: string]: string;
|
||||
};
|
||||
children?: ValidationError[];
|
||||
contexts?: {
|
||||
@ -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
150
src/pages/CheckAgeForm.tsx
Normal 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
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user