From d6ffb7b657f461503411639686b151f917941ef2 Mon Sep 17 00:00:00 2001
From: Gustavo S Frehse <gsf20@inf.ufpr.br>
Date: Mon, 7 Apr 2025 10:52:08 -0300
Subject: [PATCH] ADD zustand and new backend login

---
 package.json                           |  3 ++-
 pnpm-lock.yaml                         | 26 +++++++++++++++++++++++++
 src/app/entrar/components/LoginForm.js |  4 ++++
 src/app/entrar/page.js                 | 27 +++++++++++++-------------
 src/app/handlers/loginHandler.js       |  1 +
 src/app/stores/userStore.js            | 20 +++++++++++++++++++
 6 files changed, 66 insertions(+), 15 deletions(-)
 create mode 100644 src/app/stores/userStore.js

diff --git a/package.json b/package.json
index efa1674e..3079f894 100644
--- a/package.json
+++ b/package.json
@@ -21,7 +21,8 @@
     "react-icons": "^5.2.1",
     "react-image-crop": "^11.0.7",
     "react-swipeable": "^7.0.1",
-    "tailwind-scrollbar": "^3.1.0"
+    "tailwind-scrollbar": "^3.1.0",
+    "zustand": "^5.0.3"
   },
   "devDependencies": {
     "@svgr/webpack": "^8.1.0",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index c95bdf4a..2cbf0676 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -47,6 +47,9 @@ importers:
       tailwind-scrollbar:
         specifier: ^3.1.0
         version: 3.1.0(tailwindcss@3.4.10)
+      zustand:
+        specifier: ^5.0.3
+        version: 5.0.3(@types/react@18.3.3)(react@18.3.1)
     devDependencies:
       '@svgr/webpack':
         specifier: ^8.1.0
@@ -2762,6 +2765,24 @@ packages:
     resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
     engines: {node: '>=10'}
 
+  zustand@5.0.3:
+    resolution: {integrity: sha512-14fwWQtU3pH4dE0dOpdMiWjddcH+QzKIgk1cl8epwSE7yag43k/AD/m4L6+K7DytAOr9gGBe3/EXj9g7cdostg==}
+    engines: {node: '>=12.20.0'}
+    peerDependencies:
+      '@types/react': '>=18.0.0'
+      immer: '>=9.0.6'
+      react: '>=18.0.0'
+      use-sync-external-store: '>=1.2.0'
+    peerDependenciesMeta:
+      '@types/react':
+        optional: true
+      immer:
+        optional: true
+      react:
+        optional: true
+      use-sync-external-store:
+        optional: true
+
 snapshots:
 
   '@alloc/quick-lru@5.2.0': {}
@@ -5926,3 +5947,8 @@ snapshots:
   yaml@2.5.0: {}
 
   yocto-queue@0.1.0: {}
+
+  zustand@5.0.3(@types/react@18.3.3)(react@18.3.1):
+    optionalDependencies:
+      '@types/react': 18.3.3
+      react: 18.3.1
diff --git a/src/app/entrar/components/LoginForm.js b/src/app/entrar/components/LoginForm.js
index 141c2990..b44cbd3e 100644
--- a/src/app/entrar/components/LoginForm.js
+++ b/src/app/entrar/components/LoginForm.js
@@ -25,6 +25,7 @@ export default function LoginForm({
   handlePasswordChange,
   handleSubmit,
   errorMessage,
+  suggestionMessage,
   uppercase,
 }) {
   const [openModalSignup, setOpenModalSignup] = useState(false);
@@ -60,6 +61,9 @@ export default function LoginForm({
                 {errorMessage ? (
                   <Alert severity="error" className="mb-3">{errorMessage}</Alert>
                 ) : null}
+                {suggestionMessage ? (
+                  <Alert severity="info" className="mb-3">{suggestionMessage}</Alert>
+                ) : null}
 
                 {/* Campo de E-mail */}
                 <div className="w-full mb-6">
diff --git a/src/app/entrar/page.js b/src/app/entrar/page.js
index 5971e901..d058f54b 100644
--- a/src/app/entrar/page.js
+++ b/src/app/entrar/page.js
@@ -13,14 +13,18 @@ import { ThemeProvider } from "@emotion/react";
 import theme from "../theme";
 import LoginInfo from "./components/LoginInfo";
 import AcessibilityBar from "../components/AcessibilityBar";
+import { useUserStore } from "@/app/stores/userStore"
 
 function Login() {
   const [userEmail, setUserEmail] = useState("");
   const [userPassword, setUserPassword] = useState("");
   const [errorMessage, setErrorMessage] = useState("");
+  const [suggestionMessage, setSuggestionMessage] = useState("");
   const [isFirstLetterUpperCase, setIsFirstLetterUpperCase] = useState(false);
   const searchParams = useSearchParams();
+  const userStore = useUserStore();
   const access_token = getStoredValue("access_token");
+
   // Obtendo os parĂ¢metros de busca
   const redirectUrl = searchParams.get("redirect")
     ? searchParams.get("redirect") + (searchParams.get("params") ? `?${searchParams.get("params")}` : '')
@@ -40,7 +44,6 @@ function Login() {
   }
   };
 
-
   const handlePasswordChange = (e) => {
     setUserPassword(e.target.value);
   };
@@ -48,28 +51,23 @@ function Login() {
   const userLogin = async (event, email, password) => {
     event.preventDefault();
     await mecredApi
-      .post("/auth/sign_in", {
+      .post("/public/auth/signin", {
         email: userEmail,
         password: userPassword,
       })
       .then((response) => {
-        saveToLocalStorage("user_data", JSON.stringify(response.data["data"]));
-        saveToLocalStorage("access_token", response.headers["access-token"]);
-        saveToLocalStorage("client", response.headers["client"])
-        saveToLocalStorage("uid", response.headers["uid"])
-        saveToLocalStorage("expiry", response.headers["expiry"])
-        saveToLocalStorage("token-type", response.headers["token-type"])
+        const token = response.data['token'];
+        userStore.setToken(token);
+        saveToLocalStorage('token', token);
         router.push(redirectUrl);
       })
       .catch((error) => {
-        setErrorMessage(error['response']['data']['errors'][0])
+        console.log(error);
+        setErrorMessage(error['response']['data']['error']['message']);
+        setSuggestionMessage(error['response']['data']['error']['suggestion']);
       })
   };
 
-  useEffect(() => {
-    if (access_token) redirect(redirectUrl);
-  });
-
   return (
     <ThemeProvider theme={theme}>
       <Grid container className="bg-fundo bg-repeat bg-fixed min-h-screen">
@@ -82,6 +80,7 @@ function Login() {
             handlePasswordChange={handlePasswordChange}
             handleSubmit={userLogin}
             errorMessage={errorMessage}
+            suggestionMessage={suggestionMessage}
             uppercase={isFirstLetterUpperCase}
           />
         </Grid>
@@ -99,4 +98,4 @@ export default function LoginWrapper() {
       </div>
     </Suspense>
   );
-};
\ No newline at end of file
+};
diff --git a/src/app/handlers/loginHandler.js b/src/app/handlers/loginHandler.js
index 59dd6c7e..95813076 100644
--- a/src/app/handlers/loginHandler.js
+++ b/src/app/handlers/loginHandler.js
@@ -4,6 +4,7 @@ import { useCallback } from "react";
 import { getStoredValue } from "./localStorageHandler";
 
 export function isLoggedIn() {
+  return false;
   if (typeof window === "undefined") return undefined;
 
   return getStoredValue("access_token") ? true : false;
diff --git a/src/app/stores/userStore.js b/src/app/stores/userStore.js
new file mode 100644
index 00000000..3083b70d
--- /dev/null
+++ b/src/app/stores/userStore.js
@@ -0,0 +1,20 @@
+import mecredApi from "@/axiosConfig";
+import { create } from 'zustand';
+import { getStoredValue, removeFromLocalStorage, saveToLocalStorage } from "../handlers/localStorageHandler";
+
+const useUserStore = create((set, get) => ({
+  token: null,
+  data: null,
+  error: null,
+  setToken: async (token) => {
+    set({ token, data: null, error: null });
+  },
+  headers: () => {
+    return { 'Authorization': `Bearer ${get().token}` };
+  }
+}))
+
+// Fetch user initially, to test token saved to localStorage and to get user data
+//useUserStore.getState().fetchUser();
+
+export { useUserStore };
-- 
GitLab