From 80b99da1bd70b94f2af9d56b0c95550a15cc8f29 Mon Sep 17 00:00:00 2001 From: "charly.garcia" Date: Tue, 25 Apr 2023 15:49:37 -0300 Subject: [PATCH 1/9] feat: save changes --- apps/eo_web/src/api/auth.ts | 25 ++++ apps/eo_web/src/components/Header.tsx | 12 ++ apps/eo_web/src/layouts/LayoutDefault.tsx | 2 +- .../src/layouts/LayoutWithoutSession.tsx | 14 +++ apps/eo_web/src/router/ProtectedRoute.tsx | 10 +- apps/eo_web/src/router/routes.tsx | 4 +- apps/eo_web/src/screens/Login.tsx | 114 +++++++++++++++++- apps/eo_web/src/stores/useProfileStore.tsx | 40 ++++++ apps/eo_web/src/stores/useUserStore.tsx | 25 ---- packages/config/eslint/index.js | 1 - packages/config/tailwind/index.ts | 7 +- packages/ui/src/common/Button.tsx | 8 +- packages/ui/src/form/Input.tsx | 13 +- 13 files changed, 228 insertions(+), 47 deletions(-) create mode 100644 apps/eo_web/src/api/auth.ts create mode 100644 apps/eo_web/src/components/Header.tsx create mode 100644 apps/eo_web/src/layouts/LayoutWithoutSession.tsx create mode 100644 apps/eo_web/src/stores/useProfileStore.tsx delete mode 100644 apps/eo_web/src/stores/useUserStore.tsx diff --git a/apps/eo_web/src/api/auth.ts b/apps/eo_web/src/api/auth.ts new file mode 100644 index 00000000..b8e9d710 --- /dev/null +++ b/apps/eo_web/src/api/auth.ts @@ -0,0 +1,25 @@ +import { api } from "~/api/axios"; + +const API_URL = ""; + +interface LoginResponse { + profile: unknown; + session: unknown; +} + +export const login = async (credential: { + email: string; + password: string; +}) => { + return await api.post(`${API_URL}/v2/login`, { + email: credential.email, + password: credential.password, + }); +}; + +export const register = async (email: string, password: string) => { + return await api.post(`${API_URL}/v2/profile`, { + email, + password, + }); +}; diff --git a/apps/eo_web/src/components/Header.tsx b/apps/eo_web/src/components/Header.tsx new file mode 100644 index 00000000..ddc2240f --- /dev/null +++ b/apps/eo_web/src/components/Header.tsx @@ -0,0 +1,12 @@ +import React from "react"; + +export const Header = () => { + return ( +
+ +
+ ); +}; diff --git a/apps/eo_web/src/layouts/LayoutDefault.tsx b/apps/eo_web/src/layouts/LayoutDefault.tsx index 434b2a62..83d66fd2 100644 --- a/apps/eo_web/src/layouts/LayoutDefault.tsx +++ b/apps/eo_web/src/layouts/LayoutDefault.tsx @@ -3,7 +3,7 @@ import { type ReactNode } from "react"; export const LayoutDefault = ({ children }: { children: ReactNode }) => { return (
-
+
{children}
diff --git a/apps/eo_web/src/layouts/LayoutWithoutSession.tsx b/apps/eo_web/src/layouts/LayoutWithoutSession.tsx new file mode 100644 index 00000000..c9e36f58 --- /dev/null +++ b/apps/eo_web/src/layouts/LayoutWithoutSession.tsx @@ -0,0 +1,14 @@ +import { type ReactNode } from "react"; + +import { Header } from "~/components/Header"; + +export const LayoutWithoutSession = ({ children }: { children: ReactNode }) => { + return ( +
+
+
+ {children} +
+
+ ); +}; diff --git a/apps/eo_web/src/router/ProtectedRoute.tsx b/apps/eo_web/src/router/ProtectedRoute.tsx index fd1d04da..40920563 100644 --- a/apps/eo_web/src/router/ProtectedRoute.tsx +++ b/apps/eo_web/src/router/ProtectedRoute.tsx @@ -1,11 +1,11 @@ import { type ReactNode } from "react"; import { Navigate, Outlet } from "react-router-dom"; -import { useUserStore } from "~/stores/useUserStore"; +import { useProfileStore } from "~/stores/useProfileStore"; import { ROUTES } from "./routes"; -type UserState = "loggedIn" | "loggedOut"; +type ProfileState = "loggedIn" | "loggedOut"; const HOME = { loggedIn: ROUTES.base, @@ -17,10 +17,10 @@ export const ProtectedRoute = ({ expected, }: { children?: ReactNode; - expected: UserState | UserState[]; + expected: ProfileState | ProfileState[]; }) => { - const userState = useUserStore((state) => - state.user ? "loggedIn" : "loggedOut", + const userState = useProfileStore((state) => + state.profile ? "loggedIn" : "loggedOut", ); if (!expected.includes(userState)) { diff --git a/apps/eo_web/src/router/routes.tsx b/apps/eo_web/src/router/routes.tsx index e5b1322f..9da79adf 100644 --- a/apps/eo_web/src/router/routes.tsx +++ b/apps/eo_web/src/router/routes.tsx @@ -1,4 +1,4 @@ export const ROUTES = { - base: "app/", - login: "app/login", + base: "/app/login", + login: "/app/login", } as const; diff --git a/apps/eo_web/src/screens/Login.tsx b/apps/eo_web/src/screens/Login.tsx index 545ac613..a58c8b5d 100644 --- a/apps/eo_web/src/screens/Login.tsx +++ b/apps/eo_web/src/screens/Login.tsx @@ -1,7 +1,115 @@ +import { useState } from "react"; +import { zodResolver } from "@hookform/resolvers/zod"; +import { useMutation } from "@tanstack/react-query"; +import { useForm } from "react-hook-form"; +import { z } from "zod"; + +import { Button, Input, Typography, icons } from "@eo/ui"; + +import { login } from "~/api/auth"; +import { LayoutWithoutSession } from "~/layouts/LayoutWithoutSession"; +import { + useProfileStore, + type Profile, + type Session, +} from "~/stores/useProfileStore"; + +const newClientSchema = z.object({ + email: z + .string() + .min(1, { message: "Email is required" }) + .email({ message: "The email received it is not a valid email" }), + password: z.string().min(1, { message: "Password is required" }), +}); + +export type LoginFormSchema = z.infer; + export const Login = () => { + const setProfile = useProfileStore((state) => state.setProfile); + const setSession = useProfileStore((state) => state.setSession); + + const { mutate } = useMutation({ + mutationFn: login, + onSuccess: ({ data }) => { + setProfile(data.profile as Profile); + setSession(data.session as Session); + }, + }); + + const { + formState: { errors }, + register, + handleSubmit, + } = useForm({ resolver: zodResolver(newClientSchema) }); + + const [showPassword, setShowPassword] = useState(false); + return ( -
-

Hola

-
+ +
+
+
+ Welcome +
+ +
{ + void handleSubmit((data) => { + mutate(data); + })(e); + }} + > + + + setShowPassword((current) => !current)} + /> + ) : ( + setShowPassword((current) => !current)} + /> + ) + } + className="h-12 w-[327px] shadow-md" + type={showPassword ? "text" : "password"} + {...register("password")} + error={errors.password?.message} + /> + + Forgot password? + + + + + First time here? Create account + + +
+
+ Images showing app of Eo Care +
+
+
); }; diff --git a/apps/eo_web/src/stores/useProfileStore.tsx b/apps/eo_web/src/stores/useProfileStore.tsx new file mode 100644 index 00000000..f3eed68a --- /dev/null +++ b/apps/eo_web/src/stores/useProfileStore.tsx @@ -0,0 +1,40 @@ +import { create } from "zustand"; +import { persist } from "zustand/middleware"; + +export interface Profile { + email: string; +} +export interface Session { + app_release: null | unknown; + app_version: null | unknown; + device: null | unknown; + device_type: null | unknown; + ios_version: null | unknown; + token: string; + vendor_id: null | unknown; +} + +export interface UserStoreState { + profile: Profile | null; + setProfile(profile: Profile): void; + session: Session | null; + setSession(session: Session | null): void; +} + +export const useProfileStore = create()( + persist( + (set) => ({ + profile: null, + setProfile: (profile: Profile | null) => { + set(() => ({ profile })); + }, + session: null, + setSession: (session) => { + set(() => ({ session })); + }, + }), + { + name: "useProfileStore", + }, + ), +); diff --git a/apps/eo_web/src/stores/useUserStore.tsx b/apps/eo_web/src/stores/useUserStore.tsx deleted file mode 100644 index 44404c4d..00000000 --- a/apps/eo_web/src/stores/useUserStore.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import { create } from "zustand"; -import { persist } from "zustand/middleware"; - -export interface User { - email: string; -} - -export interface UserStoreState { - user: User | null; - setUser(user: User): void; -} - -export const useUserStore = create()( - persist( - (set) => ({ - user: null, - setUser: (user: User | null) => { - set(() => ({ user })); - }, - }), - { - name: "useUserStore", - }, - ), -); diff --git a/packages/config/eslint/index.js b/packages/config/eslint/index.js index 73579468..b8aee724 100644 --- a/packages/config/eslint/index.js +++ b/packages/config/eslint/index.js @@ -10,7 +10,6 @@ const config = { rules: { "@next/next/no-html-link-for-pages": "off", "@next/next/no-img-element": "off", - "@typescript-eslint/unbound-method": "off", "@typescript-eslint/restrict-template-expressions": "off", "@typescript-eslint/no-unused-vars": [ diff --git a/packages/config/tailwind/index.ts b/packages/config/tailwind/index.ts index d22c0a21..229b5b19 100644 --- a/packages/config/tailwind/index.ts +++ b/packages/config/tailwind/index.ts @@ -21,8 +21,8 @@ export default { 600: "#0935B7", 700: "#072889", 800: "#041A5C", - 900: "#020D2E", - DEFAULT: "#0B42E5", + 900: "#B4F9C7", + DEFAULT: "#B4F9C7", }, "primary-dark": { 50: "#E8EBF3", @@ -149,6 +149,9 @@ export default { }, white: "#FFFFFF", transparent: "transparent", + cream: { + 100: "#F8F6F3", + }, }, }, }, diff --git a/packages/ui/src/common/Button.tsx b/packages/ui/src/common/Button.tsx index 7a45e259..fb7c1a92 100644 --- a/packages/ui/src/common/Button.tsx +++ b/packages/ui/src/common/Button.tsx @@ -42,9 +42,9 @@ export const Button = forwardRef( ref={ref} type={type} className={tw( - "flex gap-2 items-center rounded-md border border-transparent focus:outline-none focus:ring-2 focus:ring-offset-0", + "flex h-12 items-center gap-2 border border-transparent focus:outline-none focus:ring-2 focus:ring-offset-0", variant === "primary" && - "bg-primary text-white hover:bg-primary-800 focus:bg-primary focus:ring-primary-100", + "bg-primary font-bold text-black hover:bg-primary-800 focus:bg-primary focus:ring-primary-100", variant === "outline" && "border-primary text-primary hover:border-primary-800 hover:text-primary-800 focus:ring-primary-100", variant === "outline-white" && @@ -52,14 +52,14 @@ export const Button = forwardRef( variant === "secondary" && "bg-primary-50 text-primary-400 hover:bg-primary-100 focus:bg-primary-50 focus:ring-primary-100", variant === "tertiary-link" && - "text-primary hover:text-primary-700 focus:text-primary-700 focus:ring-primary-700 focus:ring-1", + "text-primary hover:text-primary-700 focus:text-primary-700 focus:ring-1 focus:ring-primary-700", size === "sm" && "px-4 py-2 text-sm leading-[17px]", size === "md" && "px-[18px] py-3 text-base leading-5", size === "lg" && "px-7 py-4 text-lg leading-[22px]", disabled && [ - variant === "primary" && "bg-primary-dark-50 text-primary-white-600", + variant === "primary" && "text-black", variant === "outline" && "border-primary-dark-200 text-primary-white-600", variant === "outline-white" && diff --git a/packages/ui/src/form/Input.tsx b/packages/ui/src/form/Input.tsx index f63596c4..4790f9be 100644 --- a/packages/ui/src/form/Input.tsx +++ b/packages/ui/src/form/Input.tsx @@ -19,6 +19,7 @@ export interface InputProps extends ComponentPropsWithoutRef<"input"> { error?: FormErrorType; left?: ReactNode; right?: ReactNode; + preventEventsRightIcon?: boolean; rightWidth?: number; } @@ -36,6 +37,7 @@ export const Input = forwardRef( style, containerClassName, className, + preventEventsRightIcon, ...rest }: InputProps, ref: ForwardedRef, @@ -44,7 +46,7 @@ export const Input = forwardRef( {!!label &&