Fixed build issues

This commit is contained in:
AmirReza Jamali
2025-09-09 13:32:58 +03:30
parent d73a64fe52
commit 83bd4394fc
18 changed files with 139 additions and 80 deletions
+3 -3
View File
@@ -1,11 +1,11 @@
FROM node:20.16.0 AS builder
FROM node:22.19.0 AS builder
WORKDIR /app
# RUN apk add --no-cache libc6-compat
COPY package*.json ./
RUN npm install
RUN npm i
COPY . .
@@ -14,7 +14,7 @@ RUN npm run build
#---
FROM node:20.16.0 AS runner
FROM node:22.19.0 AS runner
WORKDIR /app
+26 -3
View File
@@ -1,7 +1,30 @@
import { ShadowBox } from "@/src/components";
"use client";
const EditCustomer = () => {
return <ShadowBox>Edit customer</ShadowBox>;
import { use } from "react";
import {
useCustomersInfiniteQuery,
useGetCustomersDetails,
} from "../../../../hooks/queries/useCustomerQueries";
import Breadcrumb from "@/components/Breadcrumbs/Breadcrumb";
import CreateCustomer from "@/components/forms/customers/CreateCustomer";
import Loading from "@/app/loading";
const EditCustomer = ({ params }: { params: Promise<{ id: string }> }) => {
const { id } = use(params);
const { isLoading, data, isError } = useGetCustomersDetails(id);
const breadcrumbItems = [
{ name: "Dashboard", href: "/" },
{ name: "Customers", href: "/customers" },
{ name: "Edit Customer", href: `/customers/edit/${id}` },
];
if (isLoading) return <Loading />;
if (isError) return <div>Error</div>;
return (
<>
<Breadcrumb items={breadcrumbItems} />
<CreateCustomer editMode defaultValues={data.data} id={id} />
</>
);
};
export default EditCustomer;
@@ -8,7 +8,7 @@ export function ContactForm() {
<ShowcaseSection title="Contact Form" className="!p-6.5">
<form action="#">
<div className="mb-4.5 flex flex-col gap-4.5 xl:flex-row">
<InputGroup
{/* <InputGroup
label="First name"
type="text"
placeholder="Enter your first name"
@@ -20,10 +20,10 @@ export function ContactForm() {
type="text"
placeholder="Enter your last name"
className="w-full xl:w-1/2"
/>
/> */}
</div>
<InputGroup
{/* <InputGroup
label="Email"
type="email"
placeholder="Enter your email address"
@@ -49,7 +49,7 @@ export function ContactForm() {
]}
/>
<TextAreaGroup label="Message" placeholder="Type your message" />
<TextAreaGroup label="Message" placeholder="Type your message" /> */}
<button className="mt-6 flex w-full justify-center rounded-lg bg-primary p-[13px] font-medium text-white hover:bg-opacity-90">
Send Message
@@ -7,7 +7,7 @@ export function SignInForm() {
return (
<ShowcaseSection title="Sign In Form" className="!p-6.5">
<form action="#">
<InputGroup
{/* <InputGroup
label="Email"
type="email"
placeholder="Enter your email address"
@@ -18,7 +18,7 @@ export function SignInForm() {
label="Password"
type="password"
placeholder="Enter your password"
/>
/> */}
<div className="mb-5.5 mt-5 flex items-center justify-between">
<Checkbox label="Remember me" minimal withBg withIcon="check" />
@@ -5,7 +5,7 @@ export function SignUpForm() {
return (
<ShowcaseSection title="Sign Up Form" className="!p-6.5">
<form action="#">
<InputGroup
{/* <InputGroup
label="Name"
type="text"
placeholder="Enter full name"
@@ -31,7 +31,7 @@ export function SignUpForm() {
type="password"
placeholder="Re-type password"
className="mb-5.5"
/>
/> */}
<button className="flex w-full justify-center rounded-lg bg-primary p-[13px] font-medium text-white hover:bg-opacity-90">
Sign Up
@@ -62,13 +62,13 @@ export function PersonalInfoForm() {
height="sm"
/>
<TextAreaGroup
{/* <TextAreaGroup
className="mb-5.5"
label="BIO"
placeholder="Write your bio here"
icon={<PencilSquareIcon />}
defaultValue="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam lacinia turpis tortor, consequat efficitur mi congue a. Curabitur cursus, ipsum ut lobortis sodales, enim arcu pellentesque lectus ac suscipit diam sem a felis. Cras sapien ex, blandit eu dui et suscipit gravida nunc. Sed sed est quis dui."
/>
/> */}
<div className="flex justify-end gap-3">
<button
+11 -10
View File
@@ -8,15 +8,16 @@ export const metadata: Metadata = {
export default function SettingsPage() {
return (
<div className="mx-auto w-full max-w-[1080px]">
<div className="grid grid-cols-5 gap-8">
<div className="col-span-5 xl:col-span-3">
<PersonalInfoForm />
</div>
<div className="col-span-5 xl:col-span-2">
<UploadPhotoForm />
</div>
</div>
</div>
<div>Settings</div>
// <div className="mx-auto w-full max-w-[1080px]">
// <div className="grid grid-cols-5 gap-8">
// <div className="col-span-5 xl:col-span-3">
// <PersonalInfoForm />
// </div>
// <div className="col-span-5 xl:col-span-2">
// <UploadPhotoForm />
// </div>
// </div>
// </div>
);
}
+43 -31
View File
@@ -2,49 +2,64 @@
import { PasswordIcon, UserIcon } from "@/assets/icons";
import InputGroup from "../FormElements/InputGroup";
import { Controller, SubmitHandler, useForm } from "react-hook-form";
import { SubmitHandler, useForm } from "react-hook-form";
import { ILoginCredentials } from "@/lib/api";
import { useLoginQuery } from "@/hooks/queries";
import { useRef, useState } from "react";
import { FormErrorMessages } from "@/constants/Texts";
export default function SigninWithPassword() {
const { handleSubmit, control, reset } = useForm<ILoginCredentials>();
const [passwordFieldInputType, setPasswordFieldInputType] = useState<
"password" | "text"
>("password");
const { handleSubmit, control, reset, register } =
useForm<ILoginCredentials>();
const { mutate, isPending } = useLoginQuery();
const passwordInputRef = useRef<HTMLInputElement>(null);
const onSubmit: SubmitHandler<ILoginCredentials> = (data) => {
mutate(data);
reset();
};
return (
<form onSubmit={handleSubmit(onSubmit)}>
<Controller
<InputGroup
type="username"
{...register("username", {
required: {
value: true,
message: FormErrorMessages.required,
},
})}
label="Username"
className="mb-4 [&_input]:py-[15px]"
placeholder="Enter your Username"
name="username"
control={control}
render={({ field: username }) => (
<InputGroup
type="username"
handleChange={(value) => username.onChange(value)}
label="Username"
className="mb-4 [&_input]:py-[15px]"
placeholder="Enter your Username"
name="username"
icon={<UserIcon />}
/>
)}
icon={<UserIcon />}
/>
<Controller
<InputGroup
type={passwordFieldInputType}
{...register("password", {
required: {
value: true,
message: FormErrorMessages.required,
},
})}
label="Password"
className="mb-5 [&_input]:py-[15px]"
placeholder="Enter your password"
name="password"
control={control}
render={({ field: password }) => (
<InputGroup
type="password"
handleChange={(value) => password.onChange(value)}
label="Password"
className="mb-5 [&_input]:py-[15px]"
placeholder="Enter your password"
name="password"
icon={<PasswordIcon />}
icon={
<PasswordIcon
className="cursor-pointer"
onClick={() => {
setPasswordFieldInputType(
passwordFieldInputType === "password" ? "text" : "password",
);
}}
/>
)}
}
/>
<div className="mb-4.5">
@@ -53,9 +68,6 @@ export default function SigninWithPassword() {
className="flex w-full cursor-pointer items-center justify-center gap-2 rounded-lg bg-primary p-4 font-medium text-white transition hover:bg-opacity-90"
>
Sign In
{/* {loading && (
<span className="inline-block h-4 w-4 animate-spin rounded-full border-2 border-solid border-white border-t-transparent dark:border-primary dark:border-t-transparent" />
)} */}
</button>
</div>
</form>
@@ -11,10 +11,11 @@ import Image from "next/image";
import Link from "next/link";
import { useState } from "react";
import { LogOutIcon, SettingsIcon, UserIcon } from "./icons";
import { useUser } from "@/contexts";
export function UserInfo() {
const [isOpen, setIsOpen] = useState(false);
const { logout } = useUser();
const USER = {
name: "John Smith",
email: "johnson@nextadmin.com",
@@ -106,7 +107,11 @@ export function UserInfo() {
<div className="p-2 text-base text-[#4B5563] dark:text-dark-6">
<button
className="flex w-full items-center gap-2.5 rounded-lg px-2.5 py-[9px] hover:bg-gray-2 hover:text-dark dark:hover:bg-dark-3 dark:hover:text-white"
onClick={() => setIsOpen(false)}
onClick={() => {
setIsOpen(false);
logout();
}}
>
<LogOutIcon />
+1 -1
View File
@@ -41,7 +41,7 @@ export function Sidebar() {
});
});
});
}, [pathname]);
}, [pathname, expandedItems]);
return (
<>
+6 -3
View File
@@ -50,11 +50,14 @@ const CompaniesTable = ({}: IProps) => {
</TableHeader>
<TableBody>
{allCompanies.map((company) =>
{allCompanies.map((company, index) =>
!company ? (
<h6>No Data was Found</h6>
<h6 key={index}>No Data was Found</h6>
) : (
<TableRow key={company.id} className="odd:bg-gray-2 dark:odd:bg-gray-7">
<TableRow
key={company.id}
className="odd:bg-gray-2 dark:odd:bg-gray-7"
>
<TableHead className="text-start" colSpan={100}>
{company.name}
</TableHead>
+5 -3
View File
@@ -46,8 +46,8 @@ const CustomersTable = () => {
</TableRow>
</TableHeader>
<TableBody>
{allCustomers.map((customer, index) => (
<TableRow key={index}>
{allCustomers.map((customer) => (
<TableRow key={customer.id}>
<TableCell colSpan={100}>{customer.full_name}</TableCell>
<TableCell colSpan={100}>{customer.email}</TableCell>
<TableCell colSpan={100}>{customer.created_at}</TableCell>
@@ -55,7 +55,9 @@ const CustomersTable = () => {
<TableCell colSpan={100}>{customer.status}</TableCell>
<TableCell colSpan={100}>
{customer.companies?.length ? (
customer.companies.map((c) => <span>{c.name}, </span>)
customer.companies.map((c) => (
<span key={c.id}>{c.name}, </span>
))
) : (
<span>None</span>
)}
+6 -4
View File
@@ -33,8 +33,10 @@ const TendersTable = () => {
</TableHeader>
<TableBody>
{allTenders.map((item) => {
return (
{allTenders.map((item, index) =>
!item ? (
<h6 key={index}>No tenders were found</h6>
) : (
<TableRow
key={item.id}
className="odd:bg-gray-2 dark:odd:bg-gray-7"
@@ -49,8 +51,8 @@ const TendersTable = () => {
{item.status}
</TableCell>
</TableRow>
);
})}
),
)}
</TableBody>
</Table>
</div>
@@ -49,11 +49,11 @@ const useTenderListPresenter = () => {
const handleFilterChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setSearch(e.target.value);
};
const onConfirmDelete = () => {
if (currentTender) {
deleteTender(currentTender.id);
}
};
// const onConfirmDelete = () => {
// if (currentTender) {
// deleteTender(currentTender.id);
// }
// };
const allTenders = data?.pages.flatMap((page) => page.data.tenders) ?? [];
return {
@@ -61,7 +61,6 @@ const useTenderListPresenter = () => {
setCurrentTender,
search,
handleFilterChange,
onConfirmDelete,
allTenders,
error,
isPending,
+3 -3
View File
@@ -1,4 +1,3 @@
// src/contexts/UserContext.tsx
"use client";
import React, {
@@ -15,6 +14,7 @@ import Cookies from "js-cookie";
import { z } from "zod";
import { UserSchema, ILoginResponse } from "../lib/api/types";
import { COOKIE_KEYS } from "../lib/shared/cookies";
import { useRouter } from "next/navigation";
type User = z.infer<typeof UserSchema>;
@@ -37,7 +37,7 @@ export const UserProvider: React.FC<UserProviderProps> = ({ children }) => {
const [user, setUser] = useState<User | null>(null);
const [accessToken, setAccessToken] = useState<string | null>(null);
const [isLoading, setIsLoading] = useState<boolean>(true);
const router = useRouter();
useEffect(() => {
try {
const tokenFromCookie = Cookies.get(COOKIE_KEYS.access_token);
@@ -88,7 +88,7 @@ export const UserProvider: React.FC<UserProviderProps> = ({ children }) => {
setAuthState,
logout,
}),
[user, accessToken, isLoading, setAuthState, logout]
[user, accessToken, isLoading, setAuthState, logout],
);
return <UserContext.Provider value={value}>{children}</UserContext.Provider>;
+8
View File
@@ -27,6 +27,7 @@ export const useCustomersInfiniteQuery = (params?: Record<string, any>) => {
initialPageParam: 0,
getNextPageParam: (lastPage) => {
if (!lastPage.meta) return;
const { offset, limit, total } = lastPage.meta;
const nextOffset = offset + limit;
@@ -42,6 +43,13 @@ export const useGetAllCustomers = () => {
queryFn: () => customersService.getCustomers(),
});
};
export const useGetCustomersDetails = (id: string) => {
const queryKey = useMemo(() => ["GET ALL CUSTOMERS", id], [id]);
return useQuery({
queryKey,
queryFn: () => customersService.customerDetails(id),
});
};
export const useAssignCompany = (id: string, successCallback?: () => void) => {
const queryClient = useQueryClient();
const mutationKey = useMemo(
@@ -49,6 +49,10 @@ export const customersService = {
throw error;
}
},
customerDetails: async (id: string) => {
const response = await api.get(API_ENDPOINTS.CUSTOMERS.DETAILS(id));
return response.data;
},
assignCompanyToCustomer: async ({
credentials,
id,
+1 -1
View File
@@ -24,6 +24,6 @@ const TenderSchema = z.object({
title: z.string(),
});
export const TendersResponse = z.object({
companies: z.array(TenderSchema).or(z.null()),
tenders: z.array(TenderSchema).or(z.null()),
});
export type TTenderResponse = z.infer<typeof TendersResponse>;