From 76c01a4830862d526d107fa44fa8e030c6fe2613 Mon Sep 17 00:00:00 2001 From: Walter Date: Tue, 10 Jun 2025 09:12:17 -0300 Subject: [PATCH 01/71] avances en login y algunos tipados --- src/app/(application)/(generator)/layout.tsx | 5 +- src/app/(application)/calendar/layout.tsx | 9 +- src/app/(application)/favs/layout.tsx | 4 +- src/app/(application)/layout.tsx | 8 +- src/app/(application)/profile/layout.tsx | 4 +- src/app/(auth)/signin/page.tsx | 7 +- src/app/(auth)/signup/page.tsx | 2 +- src/app/(landing)/layout.tsx | 5 +- src/app/layout.tsx | 8 +- src/components/auth/RegisterStepBox.tsx | 18 +-- src/components/auth/RegisterStepper.tsx | 121 +++++++++++------- src/mocks/handlers.ts | 102 +++++++-------- src/services/auth.service.ts | 2 +- src/store/useAuthStore.ts | 4 +- src/types/api/auth.types.ts | 20 ++- .../components/register-steppers.types.ts | 22 ++++ src/types/layout.ts | 3 + 17 files changed, 190 insertions(+), 154 deletions(-) create mode 100644 src/types/components/register-steppers.types.ts create mode 100644 src/types/layout.ts diff --git a/src/app/(application)/(generator)/layout.tsx b/src/app/(application)/(generator)/layout.tsx index f532fa8..4d6a743 100644 --- a/src/app/(application)/(generator)/layout.tsx +++ b/src/app/(application)/(generator)/layout.tsx @@ -2,9 +2,8 @@ 'use client'; import Container from '@/components/shared/containers/Container'; -interface LayoutProps { - children: React.ReactNode; -} +import { LayoutProps } from '@/types/layout'; + export default function GeneratorRootLayout({ children }: LayoutProps) { return ( diff --git a/src/app/(application)/calendar/layout.tsx b/src/app/(application)/calendar/layout.tsx index 307e357..24f6be8 100644 --- a/src/app/(application)/calendar/layout.tsx +++ b/src/app/(application)/calendar/layout.tsx @@ -1,12 +1,7 @@ // app/recipe-generator/layout.jsx 'use client'; - -import Container from '@/components/shared/containers/Container'; - -interface LayoutProps { - children: React.ReactNode; -} - +import { LayoutProps } from '@/types/layout'; +import Container from '@/components/shared/containers/Container'; export default function CalendarLayout({ children }: LayoutProps) { return ( diff --git a/src/app/(application)/favs/layout.tsx b/src/app/(application)/favs/layout.tsx index 0a1a3d4..b2f62e3 100644 --- a/src/app/(application)/favs/layout.tsx +++ b/src/app/(application)/favs/layout.tsx @@ -2,10 +2,8 @@ 'use client'; import Container from '@/components/shared/containers/Container'; +import { LayoutProps } from '@/types/layout'; -interface LayoutProps { - children: React.ReactNode; -} export default function FavsLayout({ children }: LayoutProps) { return ( diff --git a/src/app/(application)/layout.tsx b/src/app/(application)/layout.tsx index 5b7002d..61ec3fb 100644 --- a/src/app/(application)/layout.tsx +++ b/src/app/(application)/layout.tsx @@ -1,5 +1,6 @@ 'use client'; +import { LayoutProps } from "@/types/layout"; import Footer from "@/components/landing/Footer"; import NavbarHome from "@/components/navbars/NavbarHome"; import { useAuthStore } from "@/store/useAuthStore"; @@ -7,11 +8,8 @@ import { useRouter } from "next/navigation"; import { useEffect } from "react"; import { useHydrated } from "@/utils/useHydrated"; -interface Props { - children: React.ReactNode; -} - -export default function AppLayout({ children }: Props) { + +export default function AppLayout({ children }: LayoutProps) { const { isAuthenticated } = useAuthStore(); const hydrated = useHydrated(); // const router = useRouter(); diff --git a/src/app/(application)/profile/layout.tsx b/src/app/(application)/profile/layout.tsx index 46ea93b..296f8bd 100644 --- a/src/app/(application)/profile/layout.tsx +++ b/src/app/(application)/profile/layout.tsx @@ -2,10 +2,8 @@ 'use client'; import Container from '@/components/shared/containers/Container'; +import { LayoutProps } from '@/types/layout'; -interface LayoutProps { - children: React.ReactNode; -} export default function ProfileLayout({ children }: LayoutProps) { return ( diff --git a/src/app/(auth)/signin/page.tsx b/src/app/(auth)/signin/page.tsx index 6cf0b13..df0fe31 100644 --- a/src/app/(auth)/signin/page.tsx +++ b/src/app/(auth)/signin/page.tsx @@ -33,10 +33,9 @@ export default function SignIn() { console.log("Form submitted:", formData); const response = await login(formData.email, formData.password); - console.log("Login exitoso:", response); - useAuthStore.getState().login(response.user); - - // redirige después del login exitoso + + console.log("Login exitoso:", response.data.user); + useAuthStore.getState().login(response.data.user); router.push("/home"); } catch (error: any) { console.error("Error durante login:", error.message); diff --git a/src/app/(auth)/signup/page.tsx b/src/app/(auth)/signup/page.tsx index 43fa07f..2559ed6 100644 --- a/src/app/(auth)/signup/page.tsx +++ b/src/app/(auth)/signup/page.tsx @@ -73,7 +73,7 @@ export default function SignupPage() { setCurrentStep('email')} diff --git a/src/app/(landing)/layout.tsx b/src/app/(landing)/layout.tsx index 9f04e26..c23f875 100644 --- a/src/app/(landing)/layout.tsx +++ b/src/app/(landing)/layout.tsx @@ -1,9 +1,6 @@ import Footer from "@/components/landing/Footer"; import NavbarLanding from "@/components/navbars/NavbarLanding"; - -interface LayoutProps { - children: React.ReactNode; -} +import { LayoutProps } from '@/types/layout'; export default function LandingLayout({ children }: LayoutProps) { return ( diff --git a/src/app/layout.tsx b/src/app/layout.tsx index ccfcebe..997aa0d 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -1,16 +1,12 @@ import { Montserrat } from "next/font/google"; import "./globals.css"; - +import { LayoutProps } from "@/types/layout"; import "@fortawesome/fontawesome-svg-core/styles.css"; import { config } from "@fortawesome/fontawesome-svg-core"; config.autoAddCss = false; import "@/lib/fontawesome"; -import ClientProvider from "@/context/ClientProvider"; - -interface LayoutProps { - children: React.ReactNode; -} +import ClientProvider from "@/context/ClientProvider"; const montserrat = Montserrat({ subsets: ["latin"], diff --git a/src/components/auth/RegisterStepBox.tsx b/src/components/auth/RegisterStepBox.tsx index 7e28ff8..5a48b63 100644 --- a/src/components/auth/RegisterStepBox.tsx +++ b/src/components/auth/RegisterStepBox.tsx @@ -1,19 +1,5 @@ -import { ReactNode } from 'react'; -import { ForwardRefExoticComponent, SVGProps, RefAttributes } from 'react'; - -interface RegisterStepBoxProps { - icon: ForwardRefExoticComponent, "ref"> & { - title?: string | undefined; - titleId?: string | undefined; - } & RefAttributes>; - title: string; - description: string; - buttonText: string; - onClick: () => void; - disabled?: boolean; - completed: boolean; - color?: string; -} +import { ReactNode } from 'react'; +import { RegisterStepBoxProps } from "@/types/components/register-steppers.types"; export default function RegisterStepBox({ icon: Icon, diff --git a/src/components/auth/RegisterStepper.tsx b/src/components/auth/RegisterStepper.tsx index ecb6815..f167c03 100644 --- a/src/components/auth/RegisterStepper.tsx +++ b/src/components/auth/RegisterStepper.tsx @@ -1,29 +1,33 @@ -'use client' +"use client"; -import { useState, SetStateAction } from 'react' -import Input from '@/components/shared/form/Input' -import Checkbox from '@/components/shared/form/Checkbox' -import { useAuthStore } from '@/store/useAuthStore'; -import axios from 'axios'; -import PreferencesContainer from '../shared/preferences/PreferencesContainer'; +import { useState, SetStateAction } from "react"; +import Input from "@/components/shared/form/Input"; +import Checkbox from "@/components/shared/form/Checkbox"; +import { useAuthStore } from "@/store/useAuthStore"; +import axios from "axios"; +import PreferencesContainer from "../shared/preferences/PreferencesContainer"; +import { RegisterStepperProps } from "@/types/components/register-steppers.types"; -interface RegisterStepperProps { - step: number; - onComplete: () => void; - onBack?: () => void; -} - -export default function RegisterStepper({ step, onComplete, onBack }: RegisterStepperProps) { - const [email, setEmail] = useState('') - const [password, setPassword] = useState('') - const [confirmPass, setConfirmPass] = useState('') - const [cookingLevel, setCookingLevel] = useState<'Bajo' | 'Medio' | 'Alto'>('Medio') - const [diet, setDiet] = useState<'Omnívoro' | 'Vegetariano' | 'Vegano' | 'Otro'>('Omnívoro') - const [foodNeeds, setFoodNeeds] = useState([]) - const [allergies, setAllergies] = useState([]) - const [termsAccepted, setTermsAccepted] = useState(false) +export default function RegisterStepper({ + step, + onComplete, + onBack, +}: RegisterStepperProps) { + const [email, setEmail] = useState(""); + const [name, setName] = useState(""); + const [password, setPassword] = useState(""); + const [confirmPass, setConfirmPass] = useState(""); + const [cookingLevel, setCookingLevel] = useState<"Bajo" | "Medio" | "Alto">( + "Medio" + ); + const [diet, setDiet] = useState< + "Omnívoro" | "Vegetariano" | "Vegano" | "Otro" + >("Omnívoro"); + const [foodNeeds, setFoodNeeds] = useState([]); + const [allergies, setAllergies] = useState([]); + const [termsAccepted, setTermsAccepted] = useState(false); - const login = useAuthStore(state => state.login); + const login = useAuthStore((state) => state.login); const handlePasswordStepComplete = async () => { try { @@ -35,12 +39,12 @@ export default function RegisterStepper({ step, onComplete, onBack }: RegisterSt diet, dietaryRestrictions: foodNeeds, allergies, - favoriteCuisines: [] - } + favoriteCuisines: [], + }, }; - - const { data } = await axios.post('/api/register', userData); - + + const { data } = await axios.post("/api/register", userData); + login({ name: data.user.name, email: data.user.email, @@ -51,24 +55,37 @@ export default function RegisterStepper({ step, onComplete, onBack }: RegisterSt diet: data.user.preferences.diet, dietaryRestrictions: data.user.preferences.dietaryRestrictions, allergies: data.user.preferences.allergies, - favoriteCuisines: [] - } + favoriteCuisines: [], + }, }); - + onComplete(); } catch (error) { - console.error('Error en el registro:', error); + console.error("Error en el registro:", error); } }; - const centeredWrapperClass = "flex flex-col justify-center items-center min-h-[40vh] px-4" + const centeredWrapperClass = + "flex flex-col justify-center items-center min-h-[40vh] px-4"; // STEP 1: E-mail if (step === 1) { return (
-

Ingresá tu e-mail

+

Nombre

+ setName(e.target.value)} + placeholder="nombre" + required + inputClassName="rounded-xl p-3 text-gray-800" + /> +

+ Ingresá tu e-mail +

Asegurate de tener acceso a él.

- ) + ); } // STEP 2: Preferencias @@ -113,14 +130,22 @@ export default function RegisterStepper({ step, onComplete, onBack }: RegisterSt diet, dietaryRestrictions: foodNeeds, allergies, - favoriteCuisines: [] + favoriteCuisines: [], }} onComplete={(preferences) => { if (preferences.cookingLevel) { - setCookingLevel(preferences.cookingLevel as SetStateAction<'Bajo' | 'Medio' | 'Alto'>); + setCookingLevel( + preferences.cookingLevel as SetStateAction< + "Bajo" | "Medio" | "Alto" + > + ); } if (preferences.diet) { - setDiet(preferences.diet as SetStateAction<'Omnívoro' | 'Vegetariano' | 'Vegano' | 'Otro'>); + setDiet( + preferences.diet as SetStateAction< + "Omnívoro" | "Vegetariano" | "Vegano" | "Otro" + > + ); } if (preferences.dietaryRestrictions) { setFoodNeeds(preferences.dietaryRestrictions); @@ -136,17 +161,22 @@ export default function RegisterStepper({ step, onComplete, onBack }: RegisterSt /> - ) + ); } // STEP 3: Contraseña if (step === 3) { - const valid = password.length >= 8 && /[0-9]/.test(password) && !/1234|abcd/i.test(password) + const valid = + password.length >= 8 && + /[0-9]/.test(password) && + !/1234|abcd/i.test(password); return (
-

Creá tu contraseña

+

+ Creá tu contraseña +

Mantené tu cuenta protegida.

{ - if (password === confirmPass && valid) handlePasswordStepComplete() + if (password === confirmPass && valid) + handlePasswordStepComplete(); }} className="flex-1 bg-[#B362D8] hover:opacity-80 text-white font-semibold py-2 rounded transition" > @@ -204,8 +235,8 @@ export default function RegisterStepper({ step, onComplete, onBack }: RegisterSt
- ) + ); } - return null + return null; } diff --git a/src/mocks/handlers.ts b/src/mocks/handlers.ts index 0f932b8..5d7cf7c 100644 --- a/src/mocks/handlers.ts +++ b/src/mocks/handlers.ts @@ -30,57 +30,57 @@ export const handlers = [ console.log(id); return HttpResponse.json(mockDetailsRecipes[id], { status: 200 }); }), - http.post("/api/login", async ({ request }) => { - const body = await request.json(); - - if (!body || typeof body !== "object") { - return HttpResponse.json({ message: "Bad request" }, { status: 400 }); - } - - const { email, password } = body; - - console.log("[MSW] Login:", { email, password }); - - if (email === "test@cuoco.com" && password === "123456") { - return HttpResponse.json({ - user: { - name: "Usuario Free", - email, - token: "fake-jwt-123", - premium: false, - preferences: { - cookingLevel: "Medio", - diet: "Omnívoro", - dietaryRestrictions: ["Sin lactosa"], - allergies: [], - favoriteCuisines: [] - } - }, - }); - } - if (email === "premium@cuoco.com" && password === "123456") { - return HttpResponse.json({ - user: { - name: "Usuario Premium", - email, - token: "fake-jwt-123", - premium: true, - preferences: { - cookingLevel: "Alto", - diet: "Vegetariano", - dietaryRestrictions: ["Sin gluten"], - allergies: ["Maní"], - favoriteCuisines: [], - }, - }, - }); - } - - return HttpResponse.json( - { message: "Credenciales inválidas" }, - { status: 401 } - ); - }), + // http.post("/api/login", async ({ request }) => { + // const body = await request.json(); + + // if (!body || typeof body !== "object") { + // return HttpResponse.json({ message: "Bad request" }, { status: 400 }); + // } + + // const { email, password } = body; + + // console.log("[MSW] Login:", { email, password }); + + // if (email === "test@cuoco.com" && password === "123456") { + // return HttpResponse.json({ + // user: { + // name: "Usuario Free", + // email, + // token: "fake-jwt-123", + // premium: false, + // preferences: { + // cookingLevel: "Medio", + // diet: "Omnívoro", + // dietaryRestrictions: ["Sin lactosa"], + // allergies: [], + // favoriteCuisines: [] + // } + // }, + // }); + // } + // if (email === "premium@cuoco.com" && password === "123456") { + // return HttpResponse.json({ + // user: { + // name: "Usuario Premium", + // email, + // token: "fake-jwt-123", + // premium: true, + // preferences: { + // cookingLevel: "Alto", + // diet: "Vegetariano", + // dietaryRestrictions: ["Sin gluten"], + // allergies: ["Maní"], + // favoriteCuisines: [], + // }, + // }, + // }); + // } + + // return HttpResponse.json( + // { message: "Credenciales inválidas" }, + // { status: 401 } + // ); + // }), http.post("/api/reset-password", async ({ request }) => { const body = await request.json(); diff --git a/src/services/auth.service.ts b/src/services/auth.service.ts index 6eb80a6..f4106c1 100644 --- a/src/services/auth.service.ts +++ b/src/services/auth.service.ts @@ -3,7 +3,7 @@ import { LoginResponse, LoginRequest, ApiError } from '@/types/api/auth.types'; export async function login(email: string, password: string): Promise { try { - const response = await axios.post('/api/login', { email, password }); + const response = await axios.post('https://dev.cuoco.com.ar/api/auth/login', { email, password }); return response.data; } catch (error: any) { // Axios envuelve el error, hay que acceder al response diff --git a/src/store/useAuthStore.ts b/src/store/useAuthStore.ts index 5b40b45..042346a 100644 --- a/src/store/useAuthStore.ts +++ b/src/store/useAuthStore.ts @@ -4,7 +4,7 @@ import { User as AuthUser } from '@/types/auth/auth.types'; export type User = AuthUser; -interface AuthState { +export interface AuthState { user: User | null; isAuthenticated: boolean; login: (user: User) => void; @@ -22,7 +22,7 @@ export const useAuthStore = create()( updateUser: (user) => set({ user }), }), { - name: 'auth-storage', // ← guarda en localStorage con esta clave + name: 'auth-storage', // guarda en localStorage con esta clave } ) ); diff --git a/src/types/api/auth.types.ts b/src/types/api/auth.types.ts index b4f8a49..7fe5571 100644 --- a/src/types/api/auth.types.ts +++ b/src/types/api/auth.types.ts @@ -1,13 +1,27 @@ export interface LoginResponse { - user: { + data :{user: { + id: number; // Added 'id' name: string; email: string; - premium: boolean; + plan: { // Changed 'premium' to 'plan' object + id: number; + description: string; + }; + preferences: { // Added 'preferences' object + cookLevel: { + id: number; + description: string; + }; + diet: { + id: number; + description: string; + }; + }; token: string; }; message?: string; } - +} export interface LoginRequest { email: string; password: string; diff --git a/src/types/components/register-steppers.types.ts b/src/types/components/register-steppers.types.ts new file mode 100644 index 0000000..5e34214 --- /dev/null +++ b/src/types/components/register-steppers.types.ts @@ -0,0 +1,22 @@ +import { ForwardRefExoticComponent, SVGProps, RefAttributes } from "react"; + +export interface RegisterStepBoxProps { + icon: ForwardRefExoticComponent< + Omit, "ref"> & { + title?: string | undefined; + titleId?: string | undefined; + } & RefAttributes + >; + title: string; + description: string; + buttonText: string; + onClick: () => void; + disabled?: boolean; + completed: boolean; + color?: string; +} +export interface RegisterStepperProps { + step: number; + onComplete: () => void; + onBack?: () => void; +} diff --git a/src/types/layout.ts b/src/types/layout.ts new file mode 100644 index 0000000..0a3ae25 --- /dev/null +++ b/src/types/layout.ts @@ -0,0 +1,3 @@ +export interface LayoutProps { + children: React.ReactNode; +} From 588ce386ba9a3717a356f19c380527b7b26c5db3 Mon Sep 17 00:00:00 2001 From: Walter Date: Tue, 10 Jun 2025 19:57:25 -0300 Subject: [PATCH 02/71] avance integration --- src/components/auth/RegisterStepper.tsx | 12 +- .../shared/preferences/PreferencesSteps.tsx | 138 ++++++++++++------ src/services/getter.service.ts | 48 ++++++ src/types/auth/auth.types.ts | 32 ++-- src/types/components/preferences.types.ts | 22 ++- 5 files changed, 175 insertions(+), 77 deletions(-) create mode 100644 src/services/getter.service.ts diff --git a/src/components/auth/RegisterStepper.tsx b/src/components/auth/RegisterStepper.tsx index f167c03..a6bd37d 100644 --- a/src/components/auth/RegisterStepper.tsx +++ b/src/components/auth/RegisterStepper.tsx @@ -17,14 +17,10 @@ export default function RegisterStepper({ const [name, setName] = useState(""); const [password, setPassword] = useState(""); const [confirmPass, setConfirmPass] = useState(""); - const [cookingLevel, setCookingLevel] = useState<"Bajo" | "Medio" | "Alto">( - "Medio" - ); - const [diet, setDiet] = useState< - "Omnívoro" | "Vegetariano" | "Vegano" | "Otro" - >("Omnívoro"); - const [foodNeeds, setFoodNeeds] = useState([]); - const [allergies, setAllergies] = useState([]); + const [cookingLevel, setCookingLevel] = useState(2); + const [diet, setDiet] = useState(1); + const [foodNeeds, setFoodNeeds] = useState([]); + const [allergies, setAllergies] = useState([]); const [termsAccepted, setTermsAccepted] = useState(false); const login = useAuthStore((state) => state.login); diff --git a/src/components/shared/preferences/PreferencesSteps.tsx b/src/components/shared/preferences/PreferencesSteps.tsx index 0791261..ee763c7 100644 --- a/src/components/shared/preferences/PreferencesSteps.tsx +++ b/src/components/shared/preferences/PreferencesSteps.tsx @@ -1,7 +1,13 @@ -import React from 'react'; -import { PreferencesStepsProps, CookingLevel, DietType } from '@/types/components/preferences.types'; -import CustomCheckbox from '../form/CustomCheckbox'; -import { BRAND_COLORS } from '@/constants/colors'; +import React from "react"; +import { useState, useEffect } from "react"; +import { + PreferencesStepsProps, +} from "@/types/components/preferences.types"; +import CustomCheckbox from "../form/CustomCheckbox"; +import { BRAND_COLORS } from "@/constants/colors"; +import { PreferenceItem } from "@/types/auth/auth.types"; +import { getCookingLevels,getAllergy,getDiet,getDietaryNeed} from "@/services/getter.service"; + export default function PreferencesSteps({ currentStep, @@ -13,10 +19,41 @@ export default function PreferencesSteps({ setFoodNeeds, allergies, setAllergies, - title = "¿Cómo es tu alimentación?" + title = "¿Cómo es tu alimentación?", }: PreferencesStepsProps) { - const toggleItem = (list: string[], item: string) => { - return list.includes(item) ? list.filter(i => i !== item) : [...list, item]; + + const [cookingLevelOptions, setCookingLevelOptions] = useState([]); + const [allergyOptions, setAllergyOptions] = useState([]); + const [dietOptions, setDietOptions] = useState([]); + const [dietaryNeedOptions, setDietaryNeedOptions] = useState([]); + useEffect(() => { + async function fetchLevels() { + const levels = await getCookingLevels(); + setCookingLevelOptions(levels); + } + async function fetchtAllergy() { + const levels = await getAllergy(); + setAllergyOptions(levels); + } + async function fetchDiet() { + const levels = await getDiet(); + setDietOptions(levels); + } + async function fetchDietaryNeed() { + const levels = await getDietaryNeed(); + setDietaryNeedOptions(levels); + } + console.log(cookingLevelOptions,allergyOptions,dietOptions,dietaryNeedOptions); + fetchLevels(); + fetchDiet(); + fetchDietaryNeed(); + fetchtAllergy(); + }, []); + + const toggleItem = (list: number[], item: number) => { + return list.includes(item) + ? list.filter((i) => i !== item) + : [...list, item]; }; if (currentStep === 1) { @@ -26,44 +63,47 @@ export default function PreferencesSteps({
- {['Bajo', 'Medio', 'Alto'].map((nivel) => ( + {cookingLevelOptions.map((level) => ( ))}
- +
- {['Omnívoro', 'Vegetariano', 'Vegano', 'Otro'].map((d) => ( -
@@ -75,22 +115,27 @@ export default function PreferencesSteps({ if (currentStep === 2) { return (
-

¿Tenés alguna necesidad alimentaria especial?

+

+ ¿Tenés alguna necesidad alimentaria especial? +

- {['Sin gluten', 'Sin lactosa', 'Alta en proteínas', 'Keto', 'Ninguna en particular'].map((item) => ( -
@@ -101,30 +146,33 @@ export default function PreferencesSteps({ if (currentStep === 3) { return (
-

¿Qué ingredientes evitás o te generan alergia?

+

+ ¿Qué ingredientes evitás o te generan alergia? +

- {['Leche', 'Frutos secos', 'Soja', 'Crustáceos', 'Huevo', 'Pescados', 'Cereales', 'Maní', 'Otro', 'Ninguna en particular'].map( - (item) => ( - + ))}
); } return null; -} \ No newline at end of file +} diff --git a/src/services/getter.service.ts b/src/services/getter.service.ts new file mode 100644 index 0000000..e7b2c1d --- /dev/null +++ b/src/services/getter.service.ts @@ -0,0 +1,48 @@ +import axios from 'axios'; +import { PreferenceItem } from '@/types/auth/auth.types'; + +export async function getCookingLevels(): Promise { + try { + const response = await axios.get('https://dev.cuoco.com.ar/api/cook-level'); + return response.data.data; // o response.data, si no hay .data interno + } catch (error: any) { + const message = error.response?.data?.message || 'Error al obtener niveles de cocina'; + throw new Error(message); + } +} +export async function getAllergy(): Promise { + try { + const response = await axios.get('https://dev.cuoco.com.ar/api/allergy'); + return response.data.data; // o response.data, si no hay .data interno + } catch (error: any) { + const message = error.response?.data?.message || 'Error al obtener alergias'; + throw new Error(message); + } +} +export async function getPlan(): Promise { + try { + const response = await axios.get('https://dev.cuoco.com.ar/api/plan'); + return response.data.data; // o response.data, si no hay .data interno + } catch (error: any) { + const message = error.response?.data?.message || 'Error al obtener planes'; + throw new Error(message); + } +} +export async function getDiet(): Promise { + try { + const response = await axios.get('https://dev.cuoco.com.ar/api/diet'); + return response.data.data; // o response.data, si no hay .data interno + } catch (error: any) { + const message = error.response?.data?.message || 'Error al obtener dieta'; + throw new Error(message); + } +} +export async function getDietaryNeed(): Promise { + try { + const response = await axios.get('https://dev.cuoco.com.ar/api/dietary-need'); + return response.data.data; // o response.data, si no hay .data interno + } catch (error: any) { + const message = error.response?.data?.message || 'Error al obtener necesidades de deita'; + throw new Error(message); + } +} diff --git a/src/types/auth/auth.types.ts b/src/types/auth/auth.types.ts index 25775a5..08645af 100644 --- a/src/types/auth/auth.types.ts +++ b/src/types/auth/auth.types.ts @@ -1,5 +1,5 @@ // Tipos para el proceso de registro -export type StepKey = 'email' | 'prefs' | 'password'; +export type StepKey = "email" | "prefs" | "password"; export interface RegisterState { currentStep: StepKey | null; @@ -13,15 +13,7 @@ export interface RegisterFormData { password: string; confirmPassword: string; preferences?: UserPreferences; -} - -export interface UserPreferences { - dietaryRestrictions?: string[]; - cookingLevel?: 'Bajo' | 'Medio' | 'Alto'; - favoriteCuisines?: string[]; - allergies?: string[]; - diet?: 'Omnívoro' | 'Vegetariano' | 'Vegano' | 'Otro'; -} +} // Tipos para el proceso de inicio de sesión export interface LoginFormData { @@ -34,7 +26,23 @@ export interface LoginFormData { export interface User { email: string; name?: string; - premium?: boolean; + premium?: boolean; token?: string; preferences?: UserPreferences; -} \ No newline at end of file + plan?: { + id: number; + description: string; + }; +} + +export interface PreferenceItem { + id: number; + description: string; +} + +export interface UserPreferences { + cook_level?: number; // Ej: { id: 1, description: "Medio" } + dietaryRestrictions?: number[]; // + allergies?: number[]; // + diet?: number; // +} diff --git a/src/types/components/preferences.types.ts b/src/types/components/preferences.types.ts index a42d22a..71acd0a 100644 --- a/src/types/components/preferences.types.ts +++ b/src/types/components/preferences.types.ts @@ -1,6 +1,6 @@ import { UserPreferences } from '@/types/auth/auth.types'; -export type CookingLevel = 'Bajo' | 'Medio' | 'Alto' | ''; +//export type CookingLevel = 'Bajo' | 'Medio' | 'Alto' | ''; export type DietType = 'Omnívoro' | 'Vegetariano' | 'Vegano' | 'Otro' | ''; export interface PreferencesContainerProps { @@ -9,25 +9,23 @@ export interface PreferencesContainerProps { showBackButton?: boolean; title?: string; submitButtonText?: string; -} - +} export interface PreferencesStepsProps { currentStep: number; setCurrentStep: (step: number) => void; - level: CookingLevel; - setLevel: (level: CookingLevel) => void; - diet: DietType; - setDiet: (diet: DietType) => void; - foodNeeds: string[]; - setFoodNeeds: (needs: string[]) => void; - allergies: string[]; - setAllergies: (allergies: string[]) => void; + level: number; + setLevel: (level: number) => void; + diet: number; + setDiet: (diet: number) => void; + foodNeeds: number[]; + setFoodNeeds: (needs: number[]) => void; + allergies: number[]; + setAllergies: (allergies: number[]) => void; onComplete: () => void; showBackButton?: boolean; title?: string; submitButtonText?: string; } - export interface PreferencesModalProps { isOpen: boolean; onClose: () => void; From 09b2d3d1b9011d77c3a47d6181b675e685ec91a2 Mon Sep 17 00:00:00 2001 From: rociomonaco Date: Tue, 10 Jun 2025 20:58:11 -0300 Subject: [PATCH 03/71] fix use effect --- .../shared/preferences/PreferencesSteps.tsx | 41 +++++++++---------- 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/src/components/shared/preferences/PreferencesSteps.tsx b/src/components/shared/preferences/PreferencesSteps.tsx index ee763c7..4e3ea3b 100644 --- a/src/components/shared/preferences/PreferencesSteps.tsx +++ b/src/components/shared/preferences/PreferencesSteps.tsx @@ -26,28 +26,27 @@ export default function PreferencesSteps({ const [allergyOptions, setAllergyOptions] = useState([]); const [dietOptions, setDietOptions] = useState([]); const [dietaryNeedOptions, setDietaryNeedOptions] = useState([]); - useEffect(() => { - async function fetchLevels() { - const levels = await getCookingLevels(); - setCookingLevelOptions(levels); - } - async function fetchtAllergy() { - const levels = await getAllergy(); - setAllergyOptions(levels); - } - async function fetchDiet() { - const levels = await getDiet(); - setDietOptions(levels); - } - async function fetchDietaryNeed() { - const levels = await getDietaryNeed(); - setDietaryNeedOptions(levels); + + useEffect(() => { + async function fetchPreferences() { + try { + const [levels, allergies, diets, needs] = await Promise.all([ + getCookingLevels(), + getAllergy(), + getDiet(), + getDietaryNeed() + ]); + + setCookingLevelOptions(levels); + setAllergyOptions(allergies); + setDietOptions(diets); + setDietaryNeedOptions(needs); + } catch (error) { + console.error("Error fetching preferences:", error); + } } - console.log(cookingLevelOptions,allergyOptions,dietOptions,dietaryNeedOptions); - fetchLevels(); - fetchDiet(); - fetchDietaryNeed(); - fetchtAllergy(); + + fetchPreferences(); }, []); const toggleItem = (list: number[], item: number) => { From f4b634aa2bcc14bdf4ce6801b32abffebb1ac661 Mon Sep 17 00:00:00 2001 From: rociomonaco Date: Fri, 13 Jun 2025 00:02:07 -0300 Subject: [PATCH 04/71] fix response from getters preferences --- src/services/getter.service.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/services/getter.service.ts b/src/services/getter.service.ts index e7b2c1d..17db390 100644 --- a/src/services/getter.service.ts +++ b/src/services/getter.service.ts @@ -4,7 +4,7 @@ import { PreferenceItem } from '@/types/auth/auth.types'; export async function getCookingLevels(): Promise { try { const response = await axios.get('https://dev.cuoco.com.ar/api/cook-level'); - return response.data.data; // o response.data, si no hay .data interno + return response.data; // o response.data, si no hay .data interno } catch (error: any) { const message = error.response?.data?.message || 'Error al obtener niveles de cocina'; throw new Error(message); @@ -13,7 +13,7 @@ export async function getCookingLevels(): Promise { export async function getAllergy(): Promise { try { const response = await axios.get('https://dev.cuoco.com.ar/api/allergy'); - return response.data.data; // o response.data, si no hay .data interno + return response.data; } catch (error: any) { const message = error.response?.data?.message || 'Error al obtener alergias'; throw new Error(message); @@ -22,7 +22,7 @@ export async function getAllergy(): Promise { export async function getPlan(): Promise { try { const response = await axios.get('https://dev.cuoco.com.ar/api/plan'); - return response.data.data; // o response.data, si no hay .data interno + return response.data; } catch (error: any) { const message = error.response?.data?.message || 'Error al obtener planes'; throw new Error(message); @@ -31,7 +31,7 @@ export async function getPlan(): Promise { export async function getDiet(): Promise { try { const response = await axios.get('https://dev.cuoco.com.ar/api/diet'); - return response.data.data; // o response.data, si no hay .data interno + return response.data; } catch (error: any) { const message = error.response?.data?.message || 'Error al obtener dieta'; throw new Error(message); @@ -40,7 +40,7 @@ export async function getDiet(): Promise { export async function getDietaryNeed(): Promise { try { const response = await axios.get('https://dev.cuoco.com.ar/api/dietary-need'); - return response.data.data; // o response.data, si no hay .data interno + return response.data; } catch (error: any) { const message = error.response?.data?.message || 'Error al obtener necesidades de deita'; throw new Error(message); From 0d8b36f165bd118e6e8f2312b63f5c1eb625e2fb Mon Sep 17 00:00:00 2001 From: Walter Date: Sat, 14 Jun 2025 15:57:07 -0300 Subject: [PATCH 05/71] avanzando con registro --- src/components/auth/RegisterStepper.tsx | 12 +++++++++--- src/components/shared/form/Checkbox.tsx | 4 +--- src/services/getter.service.ts | 2 +- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/components/auth/RegisterStepper.tsx b/src/components/auth/RegisterStepper.tsx index a6bd37d..83477b0 100644 --- a/src/components/auth/RegisterStepper.tsx +++ b/src/components/auth/RegisterStepper.tsx @@ -27,6 +27,12 @@ export default function RegisterStepper({ const handlePasswordStepComplete = async () => { try { + console.log('email', email,'nombre', name, 'pasword', + password, + 'nivel cocina', cookingLevel, + 'dieta', diet, + 'needs', foodNeeds, + 'alergias', allergies,); const userData = { email, password, @@ -190,15 +196,15 @@ export default function RegisterStepper({ checked={valid} onChange={() => {}} label="Mínimo 8 caracteres con letras y números" - disabled={true} + disabled={!valid} /> {}} label="Sin secuencias como 1234 o ABCD" - disabled={true} + disabled={!valid} />
{label && (