fix(typeIssues)
This commit is contained in:
parent
1b70a7d27a
commit
5076a5b4b0
@ -6,25 +6,24 @@ import Typography from "@mui/material/Typography";
|
|||||||
import Grid from "@mui/material/Grid";
|
import Grid from "@mui/material/Grid";
|
||||||
import { UTILITY_CONSTANT } from "@/utilities/utilityConstant";
|
import { UTILITY_CONSTANT } from "@/utilities/utilityConstant";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import CustomizedInputsStyled from "@/ui/CustomizedInputsStyled";
|
|
||||||
import CustomizedButtons from "@/ui/customizedButtons";
|
import CustomizedButtons from "@/ui/customizedButtons";
|
||||||
import { useForm } from "react-hook-form";
|
import { useForm } from "react-hook-form";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { loginApi } from "@/services/api/loginApi";
|
import { loginApi } from "@/services/api/loginApi";
|
||||||
import { FormControl } from "@mui/material";
|
|
||||||
import CustomTextField from "@/ui/CustomTextField";
|
import CustomTextField from "@/ui/CustomTextField";
|
||||||
import { useRouter } from "next/navigation";
|
import { useRouter } from "next/navigation";
|
||||||
import { useDispatch, useSelector } from "react-redux";
|
import { useDispatch } from "react-redux";
|
||||||
import { RootState } from "@/services/store";
|
|
||||||
import { setAuthTokens, setUserDetails } from "@/services/store/authSlice";
|
import { setAuthTokens, setUserDetails } from "@/services/store/authSlice";
|
||||||
import { routes } from "constant/route.constant";
|
import { routes } from "constant/route.constant";
|
||||||
import { grey } from "@mui/material/colors";
|
import { grey } from "@mui/material/colors";
|
||||||
|
import Snackbar, { SnackbarCloseReason } from '@mui/material/Snackbar';
|
||||||
|
|
||||||
const loginSchema = z.object({
|
const loginSchema = z.object({
|
||||||
username: z.string(),
|
username: z.string(),
|
||||||
password: z.string(),
|
password: z.string().min(6, { message: "Password is too short" })
|
||||||
|
.max(20, { message: "Password is too long" }),
|
||||||
});
|
});
|
||||||
|
|
||||||
type LoginFormValues = z.infer<typeof loginSchema>;
|
type LoginFormValues = z.infer<typeof loginSchema>;
|
||||||
@ -33,7 +32,6 @@ export default function LoginPage() {
|
|||||||
const [loader, setLoader] = useState(false);
|
const [loader, setLoader] = useState(false);
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const {
|
const {
|
||||||
register,
|
|
||||||
handleSubmit,
|
handleSubmit,
|
||||||
formState: { errors },
|
formState: { errors },
|
||||||
control,
|
control,
|
||||||
@ -55,16 +53,37 @@ export default function LoginPage() {
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
dispatch(setUserDetails(response));
|
dispatch(setUserDetails(response));
|
||||||
|
router.push(routes.PRODUCTS)
|
||||||
setLoader(false);
|
setLoader(false);
|
||||||
router.push(routes.PRODUCTS);
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
setLoader(false);
|
setLoader(false);
|
||||||
setError("Invalid credentials");
|
setError("Invalid username or password");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
const handleClose = (
|
||||||
|
_event: React.SyntheticEvent | Event,
|
||||||
|
reason?: SnackbarCloseReason,
|
||||||
|
) => {
|
||||||
|
if (reason === 'clickaway') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setError("");
|
||||||
|
};
|
||||||
return (
|
return (
|
||||||
<main className={styles.loginPage}>
|
<main className={styles.loginPage}>
|
||||||
|
<Snackbar
|
||||||
|
open={error ? true : false}
|
||||||
|
autoHideDuration={3000}
|
||||||
|
onClose={handleClose}
|
||||||
|
message="Invalid credentials"
|
||||||
|
anchorOrigin={{ vertical: "bottom", horizontal: "right" }}
|
||||||
|
ContentProps={{
|
||||||
|
sx: {
|
||||||
|
background: "red"
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
<Grid container sx={{ height: "100%" }}>
|
<Grid container sx={{ height: "100%" }}>
|
||||||
<Grid item display={{ xs: "none", md: "block" }} md={7}>
|
<Grid item display={{ xs: "none", md: "block" }} md={7}>
|
||||||
<Box
|
<Box
|
||||||
|
@ -15,22 +15,26 @@ import HeightIcon from "@mui/icons-material/Height";
|
|||||||
import RemoveRedEyeIcon from "@mui/icons-material/RemoveRedEye";
|
import RemoveRedEyeIcon from "@mui/icons-material/RemoveRedEye";
|
||||||
import { IconButton, Tooltip } from "@mui/material";
|
import { IconButton, Tooltip } from "@mui/material";
|
||||||
import { grey } from "@mui/material/colors";
|
import { grey } from "@mui/material/colors";
|
||||||
|
import { IProducts, Product } from "@/interface/products.interface";
|
||||||
|
|
||||||
const TanStackTable = ({ data }: any) => {
|
interface TanStackTableProps {
|
||||||
const [tableData, setTableData] = useState([]);
|
data: IProducts;
|
||||||
|
}
|
||||||
|
const TanStackTable = ({ data }: TanStackTableProps) => {
|
||||||
|
const [tableData, setTableData] = useState<Product[] | []>([]);
|
||||||
const [open, setOpen] = useState(false);
|
const [open, setOpen] = useState(false);
|
||||||
const [reviewModalData, setReviewModalData] = useState([]);
|
const [reviewModalData, setReviewModalData] = useState([]);
|
||||||
const [sortOrder, setSortOrder] = useState<"asc" | "desc" | null>(null);
|
const [sortOrder, setSortOrder] = useState<"asc" | "desc" | null>(null);
|
||||||
const handleOpen = () => setOpen(true);
|
const handleOpen = () => setOpen(true);
|
||||||
const handleClose = () => setOpen(false);
|
const handleClose = () => setOpen(false);
|
||||||
|
|
||||||
const handleSort = (key: string) => {
|
const handleSort = (key: keyof Product) => {
|
||||||
let sortedData;
|
let sortedData;
|
||||||
if (sortOrder === "asc") {
|
if (sortOrder === "asc") {
|
||||||
sortedData = [...tableData].sort((a, b) => (a[key] > b[key] ? -1 : 1));
|
sortedData = [...tableData.sort((a, b) => (a[key] && b[key] ? (a[key] > b[key] ? -1 : 1) : 0))];
|
||||||
setSortOrder("desc");
|
setSortOrder("desc");
|
||||||
} else {
|
} else {
|
||||||
sortedData = [...tableData].sort((a, b) => (a[key] > b[key] ? 1 : -1));
|
sortedData = [...tableData].sort((a, b) => (a[key] && b[key] ? (a[key] > b[key] ? 1 : -1) : 0));
|
||||||
setSortOrder("asc");
|
setSortOrder("asc");
|
||||||
}
|
}
|
||||||
setTableData(sortedData);
|
setTableData(sortedData);
|
||||||
@ -56,16 +60,16 @@ const TanStackTable = ({ data }: any) => {
|
|||||||
{
|
{
|
||||||
header: "Title",
|
header: "Title",
|
||||||
accessorKey: "title",
|
accessorKey: "title",
|
||||||
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
header: "Description",
|
header: "Description",
|
||||||
accessorKey: "description",
|
accessorKey: "description",
|
||||||
cell: ({ row }: any) => (
|
cell: ({ row }: any) => (
|
||||||
<>
|
|
||||||
<Tooltip title={row.original.description}>
|
<Tooltip title={row.original.description}>
|
||||||
<p className={styles.clamp_2}>{row.original.description}</p>
|
<p className={styles.clamp_2}>{row.original.description}</p>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</>
|
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -128,7 +132,7 @@ const TanStackTable = ({ data }: any) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setTableData(data?.products);
|
setTableData(data.products);
|
||||||
}, [data]);
|
}, [data]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -136,9 +140,9 @@ const TanStackTable = ({ data }: any) => {
|
|||||||
<div className={styles.responsive_table}>
|
<div className={styles.responsive_table}>
|
||||||
<table className={styles.table}>
|
<table className={styles.table}>
|
||||||
<thead>
|
<thead>
|
||||||
{table.getHeaderGroups().map((headerGroup: any) => (
|
{table.getHeaderGroups().map((headerGroup) => (
|
||||||
<tr key={headerGroup?.id}>
|
<tr key={headerGroup?.id}>
|
||||||
{headerGroup.headers.map((header: any) => (
|
{headerGroup.headers.map((header) => (
|
||||||
<th key={header?.id} className={global.body2}>
|
<th key={header?.id} className={global.body2}>
|
||||||
{flexRender(
|
{flexRender(
|
||||||
header.column.columnDef.header,
|
header.column.columnDef.header,
|
||||||
@ -150,9 +154,9 @@ const TanStackTable = ({ data }: any) => {
|
|||||||
))}
|
))}
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{table.getRowModel().rows.map((row: any) => (
|
{table.getRowModel().rows.map((row) => (
|
||||||
<tr key={row.id}>
|
<tr key={row.id}>
|
||||||
{row.getVisibleCells().map((cell: any) => (
|
{row.getVisibleCells().map((cell) => (
|
||||||
<td key={cell.id}>
|
<td key={cell.id}>
|
||||||
{flexRender(cell.column.columnDef.cell, cell.getContext())}
|
{flexRender(cell.column.columnDef.cell, cell.getContext())}
|
||||||
</td>
|
</td>
|
||||||
|
16
src/interface/login.interface.ts
Normal file
16
src/interface/login.interface.ts
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
export interface LoginResponse {
|
||||||
|
id: number;
|
||||||
|
username: string;
|
||||||
|
email: string;
|
||||||
|
firstName: string;
|
||||||
|
lastName: string;
|
||||||
|
gender: string;
|
||||||
|
image: string;
|
||||||
|
token: string;
|
||||||
|
refreshToken: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface LoginData {
|
||||||
|
username: string;
|
||||||
|
password: string;
|
||||||
|
}
|
72
src/interface/products.interface.ts
Normal file
72
src/interface/products.interface.ts
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
export interface IProducts {
|
||||||
|
products: Product[];
|
||||||
|
total: number;
|
||||||
|
skip: number;
|
||||||
|
limit: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Product {
|
||||||
|
id: number;
|
||||||
|
title: string;
|
||||||
|
description: string;
|
||||||
|
category: Category;
|
||||||
|
price: number;
|
||||||
|
discountPercentage: number;
|
||||||
|
rating: number;
|
||||||
|
stock: number;
|
||||||
|
tags: string[];
|
||||||
|
brand?: string;
|
||||||
|
sku: string;
|
||||||
|
weight: number;
|
||||||
|
dimensions: Dimensions;
|
||||||
|
warrantyInformation: string;
|
||||||
|
shippingInformation: string;
|
||||||
|
availabilityStatus: AvailabilityStatus;
|
||||||
|
reviews: Review[];
|
||||||
|
returnPolicy: ReturnPolicy;
|
||||||
|
minimumOrderQuantity: number;
|
||||||
|
meta: Meta;
|
||||||
|
images: string[];
|
||||||
|
thumbnail: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum AvailabilityStatus {
|
||||||
|
InStock = 'In Stock',
|
||||||
|
LowStock = 'Low Stock',
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum Category {
|
||||||
|
Beauty = 'beauty',
|
||||||
|
Fragrances = 'fragrances',
|
||||||
|
Furniture = 'furniture',
|
||||||
|
Groceries = 'groceries',
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Dimensions {
|
||||||
|
width: number;
|
||||||
|
height: number;
|
||||||
|
depth: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Meta {
|
||||||
|
createdAt: Date;
|
||||||
|
updatedAt: Date;
|
||||||
|
barcode: string;
|
||||||
|
qrCode: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum ReturnPolicy {
|
||||||
|
NoReturnPolicy = 'No return policy',
|
||||||
|
The30DaysReturnPolicy = '30 days return policy',
|
||||||
|
The60DaysReturnPolicy = '60 days return policy',
|
||||||
|
The7DaysReturnPolicy = '7 days return policy',
|
||||||
|
The90DaysReturnPolicy = '90 days return policy',
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Review {
|
||||||
|
rating: number;
|
||||||
|
comment: string;
|
||||||
|
date: Date;
|
||||||
|
reviewerName: string;
|
||||||
|
reviewerEmail: string;
|
||||||
|
}
|
@ -1,25 +1,9 @@
|
|||||||
// api.ts
|
// api.ts
|
||||||
import axiosInstance from "../axios/axiosInstance";
|
import { LoginData, LoginResponse } from '@/interface/login.interface';
|
||||||
|
import axiosInstance from '../axios/axiosInstance';
|
||||||
export interface LoginResponse {
|
|
||||||
id: number;
|
|
||||||
username: string;
|
|
||||||
email: string;
|
|
||||||
firstName: string;
|
|
||||||
lastName: string;
|
|
||||||
gender: string;
|
|
||||||
image: string;
|
|
||||||
token: string;
|
|
||||||
refreshToken: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface LoginData {
|
|
||||||
username: string;
|
|
||||||
password: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Login API POST */
|
/** Login API POST */
|
||||||
export const loginApi = async (data: LoginData): Promise<LoginResponse> => {
|
export const loginApi = async (data: LoginData): Promise<LoginResponse> => {
|
||||||
const response = await axiosInstance.post<LoginResponse>("/auth/login", data);
|
const response = await axiosInstance.post<LoginResponse>('/auth/login', data);
|
||||||
return response.data;
|
return response.data;
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user