update redux

This commit is contained in:
Mac mini
2026-03-31 17:32:16 +07:00
parent 4f92253534
commit 1674632b0f
9 changed files with 226 additions and 24 deletions

View File

@@ -1,16 +1,14 @@
"use client"
import UserAddressCard from "@/components/user-profile/UserAddressCard";
import UserInfoCard from "@/components/user-profile/UserInfoCard";
import UserMetaCard from "@/components/user-profile/UserMetaCard";
import { Metadata } from "next";
import React from "react";
export const metadata: Metadata = {
title: "Next.js Profile | TailAdmin - Next.js Dashboard Template",
description:
"This is Next.js Profile page for TailAdmin - Next.js Tailwind CSS Admin Dashboard Template",
};
import { RootState } from "@/store/store";
import { useSelector } from "react-redux";
export default function Profile() {
const user = useSelector((state: RootState) => state.user.data);
console.log("Current User:", user);
return (
<div>
<div className="rounded-2xl border border-gray-200 bg-white p-5 dark:border-gray-800 dark:bg-white/[0.03] lg:p-6">

View File

@@ -4,6 +4,7 @@ import "flatpickr/dist/flatpickr.css";
import { SidebarProvider } from '@/context/SidebarContext';
import { ThemeProvider } from '@/context/ThemeContext';
import { Toaster } from 'sonner';
import StoreProvider from '@/store/StoreProvider';
const outfit = Outfit({
subsets: ["latin"],
@@ -17,9 +18,11 @@ export default function RootLayout({
return (
<html lang="en">
<body className={`${outfit.className} dark:bg-gray-900`}>
<ThemeProvider>
<SidebarProvider>{children} <Toaster closeButton richColors position="top-right" /> </SidebarProvider>
</ThemeProvider>
<StoreProvider>
<ThemeProvider>
<SidebarProvider>{children} <Toaster closeButton richColors position="top-right" /> </SidebarProvider>
</ThemeProvider>
</StoreProvider>
</body>
</html>
);

View File

@@ -3,17 +3,20 @@
import Checkbox from "@/components/form/input/Checkbox";
import Input from "@/components/form/input/InputField";
import Label from "@/components/form/Label";
import Button from "@/components/ui/button/Button";
import { ChevronLeftIcon, EyeCloseIcon, EyeIcon } from "@/icons";
import { apiGetCurrentUser, apiSignIn } from "@/service/auth";
import Link from "next/link";
import React, { useState } from "react";
import { toast } from 'sonner';
import { API } from "../../../api";
import api from "@/config/config";
import { setUserData } from "@/store/features/userSlice";
import { useDispatch } from "react-redux";
import { useRouter } from "next/navigation";
export default function SignInForm() {
const [showPassword, setShowPassword] = useState(false);
const router = useRouter();
const [showPassword, setShowPassword] = useState(false);
const dispatch = useDispatch();
const [isChecked, setIsChecked] = useState(false);
const [errorMsg, setErrorMsg] = useState("");
const [loading, setLoading] = useState(false);
@@ -60,11 +63,15 @@ const [showPassword, setShowPassword] = useState(false);
setLoading(true);
const res = await apiSignIn(formData);
console.log("API Sign In Response:", res);
if (res.status === true) {
toast.success('Đăng nhập thành công!');
const data = await apiGetCurrentUser();
console.log("Current User:", data);
console.log("Current User Data:", data);
if (data?.data) {
dispatch(setUserData(data.data));
// router.push("/profile");
}
}else{
toast.error('Email hoặc mật khẩu không đúng.');
}

27
src/interface/user.ts Normal file
View File

@@ -0,0 +1,27 @@
export interface UserProfile {
display_name: string;
full_name: string;
avatar_url: string;
bio: string;
location: string;
website: string;
country_code: string;
phone: string;
}
export interface UserRole {
id: string;
name: string;
}
export interface UserData {
id: string;
email: string;
profile: UserProfile;
token_version: number;
is_deleted: boolean;
created_at: string;
updated_at: string;
roles: UserRole[];
}

View File

@@ -0,0 +1,14 @@
'use client';
import { useRef } from 'react';
import { Provider } from 'react-redux';
import { store } from './store';
export default function StoreProvider({
children,
}: {
children: React.ReactNode;
}) {
const storeRef = useRef(store);
return <Provider store={storeRef.current}>{children}</Provider>;
}

View File

@@ -0,0 +1,29 @@
import { UserData } from '@/interface/user';
import { createSlice, PayloadAction } from '@reduxjs/toolkit';
interface UserState {
data: UserData | null;
isAuthenticated: boolean;
}
const initialState: UserState = {
data: null,
isAuthenticated: false,
};
const userSlice = createSlice({
name: 'user',
initialState,
reducers: {
setUserData: (state, action: PayloadAction<UserData>) => {
state.data = action.payload;
state.isAuthenticated = true;
},
clearUserData: (state) => {
state.data = null;
state.isAuthenticated = false;
},
},
});
export const { setUserData, clearUserData } = userSlice.actions;
export default userSlice.reducer;

11
src/store/store.ts Normal file
View File

@@ -0,0 +1,11 @@
import { configureStore } from '@reduxjs/toolkit';
import userReducer from './features/userSlice';
export const store = configureStore({
reducer: {
user: userReducer,
},
});
export type RootState = ReturnType<typeof store.getState>;
export type AppDispatch = typeof store.dispatch;