From 77758f2c29862bdeebda6ab6b453d4a0c1ab32f0 Mon Sep 17 00:00:00 2001 From: Dmitri Date: Sun, 16 Nov 2025 18:21:14 +0100 Subject: [PATCH] esercizio --- package-lock.json | 40 ++++++++++ package.json | 1 + src/App.tsx | 21 ++++-- src/index.tsx | 14 +++- src/interfaces/index.ts | 11 ++- src/pages/CheckAgeForm.tsx | 150 +++++++++++++++++++++++++++++++++++++ 6 files changed, 226 insertions(+), 11 deletions(-) create mode 100644 src/pages/CheckAgeForm.tsx diff --git a/package-lock.json b/package-lock.json index d1f2d4d..cfefa06 100644 --- a/package-lock.json +++ b/package-lock.json @@ -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", diff --git a/package.json b/package.json index 704ad45..0be4797 100644 --- a/package.json +++ b/package.json @@ -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", diff --git a/src/App.tsx b/src/App.tsx index ec0b7f1..90bdbe8 100644 --- a/src/App.tsx +++ b/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 ( - - }> - } /> - } /> - } /> - - + + }> + } /> + } /> + } /> + } /> + + ); } @@ -25,6 +27,9 @@ function Layout() {
  • Check Name
  • +
  • + Check age form +

  • @@ -45,4 +50,4 @@ function NoMatch() {

    ); -} \ No newline at end of file +} diff --git a/src/index.tsx b/src/index.tsx index 2edb089..da9b5c5 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -3,13 +3,23 @@ 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(); + +root.render( + + + + + +); // If you want to start measuring performance in your app, pass a function // to log results (for example: reportWebVitals(console.log)) // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals -reportWebVitals(); \ No newline at end of file +reportWebVitals(); diff --git a/src/interfaces/index.ts b/src/interfaces/index.ts index 0f5b798..4768f6c 100644 --- a/src/interfaces/index.ts +++ b/src/interfaces/index.ts @@ -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 +} + diff --git a/src/pages/CheckAgeForm.tsx b/src/pages/CheckAgeForm.tsx new file mode 100644 index 0000000..558aa06 --- /dev/null +++ b/src/pages/CheckAgeForm.tsx @@ -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({ + name: "", + age: 0, + dateOfBirth: new Date() + }) + const validate = useMutation({ + mutationFn: async (data: FormState): Promise => { + 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 ( +
    +

    ERRORE INVIO DATI

    + +
    + ); + } + + if (validate.isPending) { + return ( +
    +

    INVIO IN CORSO

    + +
    + ); + } + + if (validate.isSuccess) { + return ( +
    + {validate.data?.success === true &&

    DATI INVIATI VALIDI

    } + {validate.data?.success === false &&

    DATI INVIATI NON VALIDI

    } + +
    + ); + } + + + return ( +
    + { + setForm((prev) => { + return { + ...prev, + name: e.target.value + } + }); + }} + /> + + { + setForm((prev) => { + const age = Number.parseInt(e.target.value) ?? 0 + return { + ...prev, + age + } + }); + }} + /> + + { + (isAbove18) && ( + { + setForm((prev) => { + return { + ...prev, + married: !(prev.married ?? false) + } + }); + }} + /> + ) + } + { + setForm((prev) => { + const newDate = new Date(e.target.value); + return { + ...prev, + dateOfBirth: newDate, + }; + }); + }} + /> + + + +
    + ) +} + +export default CheckAgeForm +