From df9a4408d908b16fcf16acfb8ab1861b536cd532 Mon Sep 17 00:00:00 2001 From: QuocAnh189 Date: Tue, 15 Oct 2024 18:34:04 +0700 Subject: [PATCH] update category page --- .env.example | 2 +- next.config.mjs | 1 + package-lock.json | 102 +++++++++++++- package.json | 7 +- src/app/constant/regex.constant.ts | 8 ++ src/app/redux/apis/category.api.ts | 33 +++-- src/app/redux/slices/category.slice.ts | 43 ++++++ src/app/redux/store.ts | 39 +++++- src/entities/category.ts | 6 +- src/features/form/category.form/index.tsx | 131 ++++++++++++++---- src/features/form/login.form/index.tsx | 65 +++++++-- .../category.create.page/index.tsx | 2 - .../categories.page/ui/TableCategories.tsx | 58 +++++--- src/shared/assets/images/image_default.jpg | Bin 0 -> 7520 bytes src/shared/data/category.ts | 66 +-------- src/shared/interfaces/auth/model/index.ts | 4 +- .../interfaces/category/payload/index.ts | 17 ++- src/shared/interfaces/common.ts | 55 ++++++++ src/shared/interfaces/common/index.ts | 22 ++- .../interfaces/ticket/model copy/index.ts | 22 +++ .../interfaces/ticket/payload copy/index.ts | 0 src/shared/ui/layouts/MainLayout.tsx | 13 +- src/widgets/button/ButtonPrimary.tsx | 9 +- src/widgets/header/DropdownMessage.tsx | 5 +- src/widgets/header/DropdownNotification.tsx | 9 +- src/widgets/select/SelectGroupTwo.tsx | 12 +- src/widgets/table/column/ImageColumn.tsx | 12 +- src/widgets/table/column/TextColumn.tsx | 9 +- tailwind.config.ts | 11 +- 29 files changed, 569 insertions(+), 194 deletions(-) create mode 100644 src/app/constant/regex.constant.ts create mode 100644 src/app/redux/slices/category.slice.ts create mode 100644 src/shared/assets/images/image_default.jpg create mode 100644 src/shared/interfaces/common.ts create mode 100644 src/shared/interfaces/ticket/model copy/index.ts create mode 100644 src/shared/interfaces/ticket/payload copy/index.ts diff --git a/.env.example b/.env.example index fa0f109..a6d576f 100644 --- a/.env.example +++ b/.env.example @@ -1 +1 @@ -API_URL = 'https://localhost:8000/api' \ No newline at end of file +API_URL = \ No newline at end of file diff --git a/next.config.mjs b/next.config.mjs index 2ba2063..dc865c7 100644 --- a/next.config.mjs +++ b/next.config.mjs @@ -2,6 +2,7 @@ const nextConfig = { images: { domains: ['res.cloudinary.com'], + formats: ['image/webp', 'image/avif'], remotePatterns: [ { protocol: 'https', diff --git a/package-lock.json b/package-lock.json index 72d208c..94a8c40 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,7 +8,9 @@ "name": "eventhub_admin_fe", "version": "0.1.0", "dependencies": { + "@hookform/resolvers": "^3.9.0", "@reduxjs/toolkit": "^2.2.7", + "daisyui": "^4.12.13", "flatpickr": "^4.6.13", "jsvectormap": "^1.6.0", "next": "14.2.11", @@ -19,9 +21,12 @@ "react": "^18", "react-apexcharts": "^1.4.1", "react-dom": "^18", + "react-hook-form": "^7.53.0", "react-redux": "^9.1.2", + "react-toastify": "^10.0.6", "sass": "^1.79.1", - "sharp": "^0.33.5" + "sharp": "^0.33.5", + "zod": "^3.23.8" }, "devDependencies": { "@types/node": "^20", @@ -122,6 +127,14 @@ "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, + "node_modules/@hookform/resolvers": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/@hookform/resolvers/-/resolvers-3.9.0.tgz", + "integrity": "sha512-bU0Gr4EepJ/EQsH/IwEzYLsT/PEj5C0ynLQ4m+GSHS+xKH4TfSelhluTgOaoc4kA5s7eCsQbM4wvZLzELmWzUg==", + "peerDependencies": { + "react-hook-form": "^7.0.0" + } + }, "node_modules/@humanwhocodes/config-array": { "version": "0.11.14", "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", @@ -1529,7 +1542,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", - "dev": true, "engines": { "node": ">= 6" } @@ -1610,6 +1622,14 @@ "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==" }, + "node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "engines": { + "node": ">=6" + } + }, "node_modules/color": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz", @@ -1676,11 +1696,19 @@ "node": ">= 8" } }, + "node_modules/css-selector-tokenizer": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/css-selector-tokenizer/-/css-selector-tokenizer-0.8.0.tgz", + "integrity": "sha512-Jd6Ig3/pe62/qe5SBPTN8h8LeUg/pT4lLgtavPf7updwwHpvFzxvOQBHYj2LZDMjUnBzgvIUSjRcf6oT5HzHFg==", + "dependencies": { + "cssesc": "^3.0.0", + "fastparse": "^1.1.2" + } + }, "node_modules/cssesc": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", - "dev": true, "bin": { "cssesc": "bin/cssesc" }, @@ -1693,6 +1721,32 @@ "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" }, + "node_modules/culori": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/culori/-/culori-3.3.0.tgz", + "integrity": "sha512-pHJg+jbuFsCjz9iclQBqyL3B2HLCBF71BwVNujUYEvCeQMvV97R59MNK3R2+jgJ3a1fcZgI9B3vYgz8lzr/BFQ==", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } + }, + "node_modules/daisyui": { + "version": "4.12.13", + "resolved": "https://registry.npmjs.org/daisyui/-/daisyui-4.12.13.tgz", + "integrity": "sha512-BnXyQoOByUF/7wSdIKubyhXxbtL8gxwY3u2cNMkxGP39TSVJqMmlItqtpY903fQnLI/NokC+bc+ZV+PEPsppPw==", + "dependencies": { + "css-selector-tokenizer": "^0.8", + "culori": "^3", + "picocolors": "^1", + "postcss-js": "^4" + }, + "engines": { + "node": ">=16.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/daisyui" + } + }, "node_modules/damerau-levenshtein": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", @@ -2585,6 +2639,11 @@ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", "dev": true }, + "node_modules/fastparse": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/fastparse/-/fastparse-1.1.2.tgz", + "integrity": "sha512-483XLLxTVIwWK3QTrMGRqUfUpoOs/0hbQrl2oz4J0pAcm3A3bu84wxTFqGqkJzewCLdME38xJLJAxBABfQT8sQ==" + }, "node_modules/fastq": { "version": "1.17.1", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", @@ -4189,7 +4248,6 @@ "version": "8.4.47", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.47.tgz", "integrity": "sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==", - "dev": true, "funding": [ { "type": "opencollective", @@ -4234,7 +4292,6 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz", "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==", - "dev": true, "dependencies": { "camelcase-css": "^2.0.1" }, @@ -4471,6 +4528,21 @@ "react": "^18.3.1" } }, + "node_modules/react-hook-form": { + "version": "7.53.0", + "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.53.0.tgz", + "integrity": "sha512-M1n3HhqCww6S2hxLxciEXy2oISPnAzxY7gvwVPrtlczTM/1dDadXgUxDpHMrMTblDOcm/AXtXxHwZ3jpg1mqKQ==", + "engines": { + "node": ">=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/react-hook-form" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17 || ^18 || ^19" + } + }, "node_modules/react-is": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", @@ -4498,6 +4570,18 @@ } } }, + "node_modules/react-toastify": { + "version": "10.0.6", + "resolved": "https://registry.npmjs.org/react-toastify/-/react-toastify-10.0.6.tgz", + "integrity": "sha512-yYjp+omCDf9lhZcrZHKbSq7YMuK0zcYkDFTzfRFgTXkTFHZ1ToxwAonzA4JI5CxA91JpjFLmwEsZEgfYfOqI1A==", + "dependencies": { + "clsx": "^2.1.0" + }, + "peerDependencies": { + "react": ">=18", + "react-dom": ">=18" + } + }, "node_modules/react-transition-group": { "version": "4.4.5", "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz", @@ -5839,6 +5923,14 @@ "funding": { "url": "https://github.com/sponsors/sindresorhus" } + }, + "node_modules/zod": { + "version": "3.23.8", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.23.8.tgz", + "integrity": "sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } } } } diff --git a/package.json b/package.json index e41d9c2..8622d00 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,9 @@ "lint": "next lint" }, "dependencies": { + "@hookform/resolvers": "^3.9.0", "@reduxjs/toolkit": "^2.2.7", + "daisyui": "^4.12.13", "flatpickr": "^4.6.13", "jsvectormap": "^1.6.0", "next": "14.2.11", @@ -20,9 +22,12 @@ "react": "^18", "react-apexcharts": "^1.4.1", "react-dom": "^18", + "react-hook-form": "^7.53.0", "react-redux": "^9.1.2", + "react-toastify": "^10.0.6", "sass": "^1.79.1", - "sharp": "^0.33.5" + "sharp": "^0.33.5", + "zod": "^3.23.8" }, "devDependencies": { "@types/node": "^20", diff --git a/src/app/constant/regex.constant.ts b/src/app/constant/regex.constant.ts new file mode 100644 index 0000000..bfff723 --- /dev/null +++ b/src/app/constant/regex.constant.ts @@ -0,0 +1,8 @@ +export const PASSWORD_REGEX = { + upperCase: new RegExp('.*[A-Z].*'), + lowerCase: new RegExp('.*[a-z].*'), + number: new RegExp('.*\\d.*'), + specialCharacter: new RegExp('.*[`~<>?,./!@#$%^&*()\\-_+="\'|{}\\[\\];:\\\\].*') +} + +export const PHONE_REGEX = new RegExp('^[+]?[(]?[0-9]{3}[)]?[-s.]?[0-9]{3}[-s.]?[0-9]{4,6}$') diff --git a/src/app/redux/apis/category.api.ts b/src/app/redux/apis/category.api.ts index eddb488..c1f24eb 100644 --- a/src/app/redux/apis/category.api.ts +++ b/src/app/redux/apis/category.api.ts @@ -1,10 +1,13 @@ +// 'use client' import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react' -//type -import { CreateCategoryPayload } from '@shared/interfaces/category/payload' +// //type +// import { CreateCategoryPayload } from '@shared/interfaces/category/payload' //interface import { ICategory } from '@shared/interfaces/category/model' +import { IListData } from '@shared/interfaces/common' +import { IGetParam } from '@shared/interfaces/common/index' export const apiCategory = createApi({ reducerPath: 'apiCategory', @@ -24,7 +27,7 @@ export const apiCategory = createApi({ keepUnusedDataFor: 20, tagTypes: ['Category'], endpoints: (builder) => ({ - createCategory: builder.mutation({ + createCategory: builder.mutation({ query: (data) => ({ url: '/categories', method: 'POST', @@ -33,13 +36,14 @@ export const apiCategory = createApi({ invalidatesTags: ['Category'] }), - getCategories: builder.query({ - query: () => ({ + getCategories: builder.query, IGetParam>({ + query: (params) => ({ url: '/categories', - method: 'GET' + method: 'GET', + params }), providesTags: ['Category'], - transformResponse: (response: any) => response.data.items + transformResponse: (response: any) => response.data }), getCategoryById: builder.query({ @@ -47,16 +51,18 @@ export const apiCategory = createApi({ url: `/categories/${categoryId}`, method: 'GET' }), - providesTags: ['Category'] + providesTags: ['Category'], + transformResponse: (response: any) => response.data }), - updateCategory: builder.mutation>({ - query: (data) => ({ - url: `/categories/${data.id}`, + updateCategory: builder.mutation({ + query: ({ id, data }) => ({ + url: `/categories/${id}`, method: 'PUT', body: data }), - invalidatesTags: ['Category'] + invalidatesTags: ['Category'], + transformResponse: (response: any) => response.data }), deleteCategory: builder.mutation({ @@ -64,7 +70,8 @@ export const apiCategory = createApi({ url: `/categories/${categoryId}`, method: 'DELETE' }), - invalidatesTags: ['Category'] + invalidatesTags: ['Category'], + transformResponse: (response: any) => response.data }) }) }) diff --git a/src/app/redux/slices/category.slice.ts b/src/app/redux/slices/category.slice.ts new file mode 100644 index 0000000..7eb2f3b --- /dev/null +++ b/src/app/redux/slices/category.slice.ts @@ -0,0 +1,43 @@ +import { PayloadAction, createSlice } from '@reduxjs/toolkit' + +//interface +import { ICategory } from '@shared/interfaces/category/model' + +export const CategorySliceKey = 'category' + +type InitialType = { + categories: ICategory[] +} + +const initialState = { + categories: [] +} as InitialType + +const categorySlice = createSlice({ + name: CategorySliceKey, + initialState, + reducers: { + setCategories: (state, action: PayloadAction) => { + state.categories = action.payload + }, + + addCategories: (state, action: PayloadAction) => { + state.categories.push(action.payload) + }, + + updateCategories: (state, action: PayloadAction) => { + state.categories = state.categories.filter((category) => + category.id === action.payload.id ? action.payload : category + ) + }, + + removeCategories: (state, action: PayloadAction) => { + state.categories = state.categories.filter((category) => category.id !== action.payload.id) + } + } +}) + +export const { setCategories } = categorySlice.actions + +const categoryReducer = categorySlice.reducer +export default categoryReducer diff --git a/src/app/redux/store.ts b/src/app/redux/store.ts index e142a0f..f6129ec 100644 --- a/src/app/redux/store.ts +++ b/src/app/redux/store.ts @@ -3,17 +3,52 @@ import { setupListeners } from '@reduxjs/toolkit/query' //api import { apiAuth } from './apis/auth.api' +import { apiCategory } from './apis/category.api' +import { apiCommand } from './apis/command.api' +import { apiEvent } from './apis/event.api' +import { apiMessage } from './apis/message.api' +import { apiPayment } from './apis/payment.api' +import { apiConversation } from './apis/conversation.api' +import { apiRole } from './apis/roles.api' +import { apiTicket } from './apis/ticket.api' +import { apiUser } from './apis/user.api' +import { apiPermission } from './apis/permission.api' +import { apiFunction } from './apis/function.api' const store = configureStore({ reducer: { - [apiAuth.reducerPath]: apiAuth.reducer + [apiAuth.reducerPath]: apiAuth.reducer, + [apiCategory.reducerPath]: apiCategory.reducer, + [apiCommand.reducerPath]: apiCommand.reducer, + [apiEvent.reducerPath]: apiEvent.reducer, + [apiMessage.reducerPath]: apiMessage.reducer, + [apiPayment.reducerPath]: apiPayment.reducer, + [apiConversation.reducerPath]: apiConversation.reducer, + [apiRole.reducerPath]: apiRole.reducer, + [apiTicket.reducerPath]: apiTicket.reducer, + [apiUser.reducerPath]: apiUser.reducer, + [apiPermission.reducerPath]: apiPermission.reducer, + [apiFunction.reducerPath]: apiFunction.reducer }, middleware: (getDefaultMiddleware) => getDefaultMiddleware({ serializableCheck: false, immutableCheck: false - }).concat([apiAuth.middleware]) + }).concat([ + apiAuth.middleware, + apiCategory.middleware, + apiCommand.middleware, + apiEvent.middleware, + apiMessage.middleware, + apiPayment.middleware, + apiConversation.middleware, + apiRole.middleware, + apiTicket.middleware, + apiUser.middleware, + apiPermission.middleware, + apiFunction.middleware + ]) }) setupListeners(store.dispatch) diff --git a/src/entities/category.ts b/src/entities/category.ts index 767ba59..084a8b6 100644 --- a/src/entities/category.ts +++ b/src/entities/category.ts @@ -1,6 +1,8 @@ export interface ICategory { id?: string name: string - status: string - icon: string + iconImageUrl: string + color: string + createdAt: Date + updatedAt: Date } diff --git a/src/features/form/category.form/index.tsx b/src/features/form/category.form/index.tsx index 75bbb00..c65effd 100644 --- a/src/features/form/category.form/index.tsx +++ b/src/features/form/category.form/index.tsx @@ -1,68 +1,143 @@ 'use client' -import React, { FC } from 'react' +import React, { FC, use, useEffect } from 'react' //next import Image from 'next/image' //components -import Select from '@widgets/select/SelectGroupTwo' import ButtonPrimary from '@widgets/button/ButtonPrimary' -const options = [ - { value: 'active', label: 'Active' }, - { value: 'Inactive', label: 'Inactive' } -] +//form +import { SubmitHandler, useForm } from 'react-hook-form' +import * as z from 'zod' +import { zodResolver } from '@hookform/resolvers/zod' + +//interface +import { + CreateCategoryPayload, + UpdateCategoryPayload, + initCreateCategoryPayload +} from '@shared/interfaces/category/payload' + +//redux +import { + useCreateCategoryMutation, + useGetCategoryByIdQuery, + useUpdateCategoryMutation +} from '@app/redux/apis/category.api' + +//image +import image_default from '@shared/assets/images/image_default.jpg' +import { toast } from 'react-toastify' + +const formSchema = z.object({ + iconImageUrl: z.any(), + name: z.string().min(1, 'Name is not empty').max(32, { message: 'Name must not exceed 32 characters' }), + color: z.string().min(1, 'Color is not empty').max(12, { message: 'phone must not exceed 12 characters' }) +}) interface Props { id: string | null } const CategoryForm: FC = ({ id }) => { - const data = id ? 'Update Category' : 'Create Category' + const { data } = id ? useGetCategoryByIdQuery(id!) : { data: null } + const [CreateCategory, { isLoading: loadingCreate }] = useCreateCategoryMutation() + const [UpdateCategory, { isLoading: loadingUpdate }] = useUpdateCategoryMutation() + + const { + register, + handleSubmit, + formState: { errors }, + setValue + } = useForm({ + resolver: zodResolver(formSchema), + defaultValues: initCreateCategoryPayload + }) + + useEffect(() => { + if (data) { + Object.keys(data).forEach((key: any) => { + setValue(key, data[key as keyof typeof data]) + }) + } + }, [data]) + + const onSubmit: SubmitHandler = async (data) => { + const formData = new FormData() + + Object.keys(data).forEach((key: any) => { + formData.append(key, data[key as keyof typeof data]) + }) - console.log(data) + try { + const result = id ? await UpdateCategory({ id: data.id!, data: formData }) : await CreateCategory(formData) + if (result.error) { + console.log(result.error) + return toast.error('Loi') + } + toast.success('Success') + } catch (error: any) { + console.log(error) + } + } - const handleCreate = () => {} + const handleFileChange = (e: React.ChangeEvent) => { + const file = e.target.files?.[0] + if (file) { + setValue('iconImageUrl', file) + } + } return ( -
+

Category

- - + +
- + + {errors.name &&

{errors.name.message}

}
- + {errors.color &&

{errors.color.message}

} +
- - + + ) } diff --git a/src/features/form/login.form/index.tsx b/src/features/form/login.form/index.tsx index 73d9f1a..4d30a49 100644 --- a/src/features/form/login.form/index.tsx +++ b/src/features/form/login.form/index.tsx @@ -1,5 +1,8 @@ 'use client' -import React from 'react' +import React, { useRef, useState } from 'react' + +//next +import { useRouter } from 'next/navigation' //icon import { IconEmail } from '@shared/assets/svgs/ui/common/IconEmail' @@ -8,25 +11,54 @@ import { IconLock } from '@shared/assets/svgs/ui/common/IconLock' // redux import { useSignInMutation } from '@app/redux/apis/auth.api' +import { IAuth } from '@shared/interfaces/auth/model' +import { useAppDispatch } from '@app/hooks/useRedux' const LoginForm = () => { - const [Login] = useSignInMutation() + const route = useRouter() + const dispatch = useAppDispatch() + const [Login, { isLoading }] = useSignInMutation() + + const identity = useRef(null) + const password = useRef(null) + + const [showPassword, setShowPassword] = useState(false) const handleSubmit = async (e: React.FormEvent) => { e.preventDefault() - await Login({ identity: '', password: '' }) + const data = { identity: identity.current?.value!, password: password.current?.value! } + try { + const result: IAuth = await Login(data).unwrap() + if (result) { + localStorage.setItem('token', JSON.stringify(result)) + + // const response = await fetch(`${process.env.NEXT_PUBLIC_API_URL}/auth/profile`, { + // headers: { Authorization: `Bearer ${result.accessToken}` } + // }) + + // const user = await response.json() + + // if (user) { + // dispatch(setUser(user.data)) + // route.push('/organization') + // } + + route.push('/') + } + } catch (error) { + console.log(error) + } } return (
- +
@@ -37,12 +69,18 @@ const LoginForm = () => {
-
diff --git a/src/widgets/button/ButtonPrimary.tsx b/src/widgets/button/ButtonPrimary.tsx index 8ca3637..20d0f84 100644 --- a/src/widgets/button/ButtonPrimary.tsx +++ b/src/widgets/button/ButtonPrimary.tsx @@ -2,17 +2,20 @@ import React, { FC } from 'react' interface Props { title: string - onClick: () => void + type?: 'button' | 'submit' | 'reset' + onClick?: () => void + loading?: boolean } -const ButtonPrimary: FC = ({ title, onClick }) => { +const ButtonPrimary: FC = ({ title, onClick, type = 'button', loading }) => { return (
) diff --git a/src/widgets/header/DropdownMessage.tsx b/src/widgets/header/DropdownMessage.tsx index 5c2e6f3..4127a55 100644 --- a/src/widgets/header/DropdownMessage.tsx +++ b/src/widgets/header/DropdownMessage.tsx @@ -9,8 +9,7 @@ import MessageItem from './ui/MessageItem' import { IconMessage } from '@shared/assets/svgs/ui/header/IconMessage' const message = { - avatar: - 'https://res.cloudinary.com/dadvtny30/image/upload/v1710062870/portfolio/frj9fscqteb90eumokqj.jpg', + avatar: 'https://res.cloudinary.com/dadvtny30/image/upload/v1710062870/portfolio/frj9fscqteb90eumokqj.jpg', name: 'Mariya Desoja', content: 'I like your confidence 💪', time: '2min ago' @@ -52,7 +51,7 @@ const DropdownMessage = () => {
    {Array.from({ length: 5 }).map((_, i) => ( - + ))}
diff --git a/src/widgets/header/DropdownNotification.tsx b/src/widgets/header/DropdownNotification.tsx index efa5b9e..cc04d0f 100644 --- a/src/widgets/header/DropdownNotification.tsx +++ b/src/widgets/header/DropdownNotification.tsx @@ -13,8 +13,7 @@ import { IconNotify } from '@shared/assets/svgs/ui/header/IconNotify' const notification = { title: 'Edit your information in a swipe', - description: - 'Sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim.', + description: 'Sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim.', time: '12 May, 2025' } @@ -49,14 +48,12 @@ const DropdownNotification = () => { className={`absolute -right-27 mt-2.5 flex h-90 w-75 flex-col rounded-sm border border-stroke bg-white shadow-default dark:border-strokedark dark:bg-boxdark sm:right-0 sm:w-80`} >
-
- Notification -
+
Notification
    {Array.from({ length: 5 }).map((_, i: number) => ( - + ))}
diff --git a/src/widgets/select/SelectGroupTwo.tsx b/src/widgets/select/SelectGroupTwo.tsx index e889f17..600ff95 100644 --- a/src/widgets/select/SelectGroupTwo.tsx +++ b/src/widgets/select/SelectGroupTwo.tsx @@ -3,7 +3,7 @@ import React, { useState, FC } from 'react' //icon import { IconChevronDown } from '@shared/assets/svgs/ui/common/IconChevronDown' -import { ISelect } from '@shared/interfaces/common' +import { ISelect } from '@shared/interfaces/common/index' interface Props { title: string @@ -20,9 +20,7 @@ const Select: FC = ({ options = [], title }) => { return (
- +