refactor(logo): Update main logo SVG to use currentColor
The main logo SVG has been replaced with an updated version. The previous logo had hardcoded fill colors, making it difficult to adapt to different color schemes, such as light and dark modes. The new SVG uses `fill="currentColor"`, which allows its color to be controlled via the parent element's CSS `color` property. This makes the logo easily themeable and more flexible for use throughout the application.
This commit is contained in:
@@ -63,7 +63,7 @@ const InputGroup = <T extends FieldValues>({
|
||||
className="text-body-sm font-medium text-dark dark:text-white"
|
||||
>
|
||||
{label}
|
||||
{required && <span className="text-red ml-1 select-none">*</span>}
|
||||
{required && <span className="ml-1 select-none text-error">*</span>}
|
||||
</label>
|
||||
|
||||
<div
|
||||
|
||||
@@ -55,7 +55,7 @@ export function Select<T extends FieldValues>({
|
||||
className="block text-body-sm font-medium text-dark dark:text-white"
|
||||
>
|
||||
{label}
|
||||
{required && <span className="text-red ml-1 select-none">*</span>}
|
||||
{required && <span className="ml-1 select-none text-error">*</span>}
|
||||
</label>
|
||||
|
||||
<div className="relative">
|
||||
|
||||
@@ -40,7 +40,7 @@ const CompaniesTable = ({}: IProps) => {
|
||||
{columns.map((columns) => (
|
||||
<TableHead
|
||||
colSpan={100}
|
||||
className="text-start font-extrabold"
|
||||
className="text-start font-extrabold uppercase"
|
||||
key={columns}
|
||||
>
|
||||
{columns}
|
||||
|
||||
@@ -32,7 +32,7 @@ export const useCompanyListPresenter = () => {
|
||||
"country",
|
||||
"state",
|
||||
"city",
|
||||
"postal_code",
|
||||
"postal code",
|
||||
"language",
|
||||
"currency",
|
||||
"employee count",
|
||||
|
||||
@@ -17,6 +17,7 @@ import AssignToCompanyModalContent from "./AssignToCompanyModalContent";
|
||||
import Modal from "@/components/ui/modal";
|
||||
import { TAssignCustomerToCompanyCredentials } from "@/lib/api";
|
||||
import { toast } from "react-toastify";
|
||||
import Status from "@/components/ui/Status";
|
||||
const CustomersTable = () => {
|
||||
const {
|
||||
isPending,
|
||||
@@ -63,7 +64,9 @@ const CustomersTable = () => {
|
||||
<TableCell colSpan={100}>{customer.email}</TableCell>
|
||||
<TableCell colSpan={100}>{customer.created_at}</TableCell>
|
||||
<TableCell colSpan={100}>{customer.type}</TableCell>
|
||||
<TableCell colSpan={100}>{customer.status}</TableCell>
|
||||
<TableCell colSpan={100}>
|
||||
<Status status={customer.status}>{customer.status}</Status>
|
||||
</TableCell>
|
||||
<TableCell colSpan={100}>
|
||||
{customer.companies?.length ? (
|
||||
customer.companies.map((c) => (
|
||||
|
||||
@@ -10,33 +10,20 @@ import {
|
||||
|
||||
export function TendersSkeleton() {
|
||||
return (
|
||||
<div className="rounded-[10px] bg-white px-7.5 pb-4 pt-7.5 shadow-1 dark:bg-gray-dark dark:shadow-card">
|
||||
<h2 className="mb-5.5 text-body-2xlg font-bold text-dark dark:text-white">
|
||||
Tenders
|
||||
</h2>
|
||||
|
||||
<Table>
|
||||
<TableHeader>
|
||||
<TableRow className="border-none uppercase [&>th]:text-center">
|
||||
<TableHead>Full name</TableHead>
|
||||
<TableHead>Email</TableHead>
|
||||
<TableHead>Type</TableHead>
|
||||
<TableHead>Status</TableHead>
|
||||
<TableHead>Company</TableHead>
|
||||
<TableHead>Actions</TableHead>
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
|
||||
<TableBody>
|
||||
{Array.from({ length: 5 }).map((_, i) => (
|
||||
<TableRow key={i}>
|
||||
<TableCell colSpan={100}>
|
||||
<Skeleton className="h-8" />
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</div>
|
||||
<TableBody>
|
||||
{Array.from({ length: 5 }).map((_, i) => (
|
||||
<TableRow key={i}>
|
||||
<TableCell colSpan={100}>
|
||||
<Skeleton className="h-8" />
|
||||
</TableCell>
|
||||
<TableCell colSpan={100}>
|
||||
<Skeleton className="h-8" />
|
||||
</TableCell>
|
||||
<TableCell colSpan={100}>
|
||||
<Skeleton className="h-8" />
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
"use client";
|
||||
|
||||
import useTenderListPresenter from "./useTenderListPresenter";
|
||||
|
||||
import Status from "@/components/ui/Status";
|
||||
import {
|
||||
Table,
|
||||
TableBody,
|
||||
@@ -30,6 +30,9 @@ const TendersTable = () => {
|
||||
<Table>
|
||||
<TableHeader>
|
||||
<TableRow className="border-none uppercase [&>th]:text-start">
|
||||
<TableHead colSpan={100} className="text-start font-extrabold">
|
||||
Row
|
||||
</TableHead>
|
||||
<TableHead colSpan={100} className="text-start font-extrabold">
|
||||
Title
|
||||
</TableHead>
|
||||
@@ -42,6 +45,7 @@ const TendersTable = () => {
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
|
||||
{isPending && <TendersSkeleton />}
|
||||
<TableBody>
|
||||
{allTenders.map((item, index) =>
|
||||
!item ? (
|
||||
@@ -52,6 +56,9 @@ const TendersTable = () => {
|
||||
key={item.id}
|
||||
className="odd:bg-gray-2 dark:odd:bg-gray-7"
|
||||
>
|
||||
<TableCell className="text-start" colSpan={100}>
|
||||
{index + 1}
|
||||
</TableCell>
|
||||
<TableCell className="text-start" colSpan={100}>
|
||||
{item.title}
|
||||
</TableCell>
|
||||
@@ -59,21 +66,14 @@ const TendersTable = () => {
|
||||
{item.country_code}
|
||||
</TableCell>
|
||||
<TableCell className={cn(`text capitalize`)} colSpan={100}>
|
||||
<span
|
||||
className={cn(
|
||||
"rounded-2xl p-2",
|
||||
getStatusColor(item.status),
|
||||
)}
|
||||
>
|
||||
{item.status}
|
||||
</span>
|
||||
<Status status={item.status}>{item.status}</Status>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
),
|
||||
)}
|
||||
</TableBody>
|
||||
{isFetchingNextPage && <TendersSkeleton />}
|
||||
</Table>
|
||||
{isFetchingNextPage && <TendersSkeleton />}
|
||||
{(data?.pages.length ?? 0) >= 5 && hasNextPage && (
|
||||
<button
|
||||
onClick={() => fetchNextPage()}
|
||||
|
||||
@@ -45,6 +45,7 @@ const CreateAdminForm: FC<IProps> = ({ defaultValues, editMode, id }) => {
|
||||
})}
|
||||
label="Full name"
|
||||
placeholder="Full name"
|
||||
required
|
||||
type="text"
|
||||
name="full_name"
|
||||
/>
|
||||
@@ -60,6 +61,7 @@ const CreateAdminForm: FC<IProps> = ({ defaultValues, editMode, id }) => {
|
||||
label="Username"
|
||||
placeholder="Username"
|
||||
autoComplete="off"
|
||||
required
|
||||
type="text"
|
||||
{...register("username", {
|
||||
required: {
|
||||
@@ -94,6 +96,7 @@ const CreateAdminForm: FC<IProps> = ({ defaultValues, editMode, id }) => {
|
||||
autoComplete="off"
|
||||
placeholder="Email"
|
||||
type="email"
|
||||
required
|
||||
{...register("email", {
|
||||
required: {
|
||||
value: true,
|
||||
@@ -117,7 +120,8 @@ const CreateAdminForm: FC<IProps> = ({ defaultValues, editMode, id }) => {
|
||||
<InputGroup
|
||||
label="Password"
|
||||
placeholder="Password"
|
||||
autoComplete="off"
|
||||
autoComplete="new-password"
|
||||
required
|
||||
type="password"
|
||||
{...register("password", {
|
||||
required: {
|
||||
|
||||
@@ -9,6 +9,7 @@ import { Select } from "@/components/FormElements/select";
|
||||
import { CurrencyIcon, GlobeIcon, MoneyIcon } from "@/assets/icons";
|
||||
import MultiSelect from "@/components/FormElements/MultiSelect";
|
||||
import { TextAreaGroup } from "@/components/FormElements/InputGroup/text-area";
|
||||
import { PHONE_REGEX } from "@/constants/regex";
|
||||
|
||||
interface IProps {
|
||||
editMode?: boolean;
|
||||
@@ -34,7 +35,7 @@ const CreateCompany = ({ defaultValues, editMode, id }: IProps) => {
|
||||
});
|
||||
return (
|
||||
<form
|
||||
className="grid grid-cols-1 items-start gap-9 rounded-xl bg-gray-1 p-10 sm:grid-cols-2"
|
||||
className="grid grid-cols-1 items-start gap-9 rounded-xl bg-gray-1 p-10 dark:bg-gray-7 sm:grid-cols-2"
|
||||
onSubmit={handleSubmit(onSubmit)}
|
||||
>
|
||||
<div className="flex flex-col gap-9">
|
||||
@@ -56,6 +57,7 @@ const CreateCompany = ({ defaultValues, editMode, id }: IProps) => {
|
||||
})}
|
||||
label="Name"
|
||||
name="name"
|
||||
required
|
||||
type="text"
|
||||
placeholder="Enter Company Name"
|
||||
/>
|
||||
@@ -72,6 +74,7 @@ const CreateCompany = ({ defaultValues, editMode, id }: IProps) => {
|
||||
})}
|
||||
label="Email"
|
||||
name="email"
|
||||
required
|
||||
type="email"
|
||||
placeholder="Enter Company Email"
|
||||
/>
|
||||
@@ -89,9 +92,14 @@ const CreateCompany = ({ defaultValues, editMode, id }: IProps) => {
|
||||
value: 20,
|
||||
message: FormErrorMessages.maxLength(20),
|
||||
},
|
||||
pattern: {
|
||||
value: PHONE_REGEX,
|
||||
message: FormErrorMessages.invalidPattern,
|
||||
},
|
||||
})}
|
||||
label="Phone"
|
||||
name="phone"
|
||||
required
|
||||
type="tel"
|
||||
placeholder="Enter Company Phone"
|
||||
/>
|
||||
@@ -104,6 +112,7 @@ const CreateCompany = ({ defaultValues, editMode, id }: IProps) => {
|
||||
})}
|
||||
name="type"
|
||||
label="Company type"
|
||||
required
|
||||
items={[
|
||||
{ value: "private", label: "Private" },
|
||||
{ value: "public", label: "Public" },
|
||||
@@ -129,6 +138,7 @@ const CreateCompany = ({ defaultValues, editMode, id }: IProps) => {
|
||||
label="Registration Number"
|
||||
name="registration_number"
|
||||
type="text"
|
||||
required
|
||||
placeholder="Enter Registration Number"
|
||||
/>
|
||||
{errors.registration_number && (
|
||||
@@ -148,6 +158,7 @@ const CreateCompany = ({ defaultValues, editMode, id }: IProps) => {
|
||||
label="Tax id"
|
||||
name="tax_id"
|
||||
type="text"
|
||||
required
|
||||
placeholder="Enter Tax id"
|
||||
/>
|
||||
{errors.tax_id && (
|
||||
@@ -165,6 +176,7 @@ const CreateCompany = ({ defaultValues, editMode, id }: IProps) => {
|
||||
label="Industry"
|
||||
name="industry"
|
||||
type="text"
|
||||
required
|
||||
placeholder="Enter Industry"
|
||||
/>
|
||||
{errors.industry && (
|
||||
@@ -202,6 +214,7 @@ const CreateCompany = ({ defaultValues, editMode, id }: IProps) => {
|
||||
},
|
||||
})}
|
||||
label="Website"
|
||||
required
|
||||
name="website"
|
||||
type="url"
|
||||
placeholder="Enter Company Website"
|
||||
@@ -212,116 +225,7 @@ const CreateCompany = ({ defaultValues, editMode, id }: IProps) => {
|
||||
</p>
|
||||
)}
|
||||
</ShowcaseSection>
|
||||
<ShowcaseSection
|
||||
title="Contact Person"
|
||||
className="grid grid-cols-1 gap-5"
|
||||
>
|
||||
<InputGroup
|
||||
{...register("contact_person.full_name", {
|
||||
required: { value: true, message: FormErrorMessages.required },
|
||||
minLength: {
|
||||
value: 2,
|
||||
message: FormErrorMessages.minLength(2),
|
||||
},
|
||||
maxLength: {
|
||||
value: 100,
|
||||
message: FormErrorMessages.maxLength(100),
|
||||
},
|
||||
})}
|
||||
label="Full name"
|
||||
name="contact_person.full_name"
|
||||
placeholder="Enter Full name"
|
||||
type="text"
|
||||
/>
|
||||
{errors.contact_person?.full_name && (
|
||||
<p className="mt-1 text-sm text-red-500">
|
||||
{errors.contact_person.full_name.message}
|
||||
</p>
|
||||
)}
|
||||
<InputGroup
|
||||
{...register("contact_person.position", {
|
||||
required: { value: true, message: FormErrorMessages.required },
|
||||
minLength: {
|
||||
value: 2,
|
||||
message: FormErrorMessages.minLength(2),
|
||||
},
|
||||
maxLength: {
|
||||
value: 100,
|
||||
message: FormErrorMessages.maxLength(100),
|
||||
},
|
||||
})}
|
||||
label="Position"
|
||||
name="contact_person.position"
|
||||
placeholder="Enter Content Person Position"
|
||||
type="text"
|
||||
/>
|
||||
{errors.contact_person?.position && (
|
||||
<p className="mt-1 text-sm text-red-500">
|
||||
{errors.contact_person.position.message}
|
||||
</p>
|
||||
)}
|
||||
<InputGroup
|
||||
{...register("contact_person.email", {
|
||||
required: { value: true, message: FormErrorMessages.required },
|
||||
pattern: {
|
||||
value: /^[^\s@]+@[^\s@]+\.[^\s@]+$/,
|
||||
message: FormErrorMessages.invalidEmail,
|
||||
},
|
||||
})}
|
||||
label="Email"
|
||||
name="contact_person.email"
|
||||
placeholder="Enter Contact Person Email"
|
||||
type="email"
|
||||
/>
|
||||
{errors.contact_person?.email && (
|
||||
<p className="mt-1 text-sm text-red-500">
|
||||
{errors.contact_person.email.message}
|
||||
</p>
|
||||
)}
|
||||
<InputGroup
|
||||
{...register("contact_person.phone", {
|
||||
required: { value: true, message: FormErrorMessages.required },
|
||||
minLength: {
|
||||
value: 10,
|
||||
message: FormErrorMessages.minLength(10),
|
||||
},
|
||||
maxLength: {
|
||||
value: 20,
|
||||
message: FormErrorMessages.maxLength(20),
|
||||
},
|
||||
})}
|
||||
label="Phone"
|
||||
name="contact_person.phone"
|
||||
placeholder="Enter Contact Person Phone"
|
||||
type="tel"
|
||||
/>
|
||||
{errors.contact_person?.phone && (
|
||||
<p className="mt-1 text-sm text-red-500">
|
||||
{errors.contact_person.phone.message}
|
||||
</p>
|
||||
)}
|
||||
<InputGroup
|
||||
{...register("contact_person.mobile", {
|
||||
minLength: {
|
||||
value: 10,
|
||||
message: FormErrorMessages.minLength(10),
|
||||
},
|
||||
maxLength: {
|
||||
value: 20,
|
||||
message: FormErrorMessages.maxLength(20),
|
||||
},
|
||||
})}
|
||||
label="Mobile"
|
||||
name="contact_person.mobile"
|
||||
placeholder="Enter Contact Person Mobile"
|
||||
type="tel"
|
||||
/>
|
||||
{errors.contact_person?.mobile && (
|
||||
<p className="mt-1 text-sm text-red-500">
|
||||
{errors.contact_person.mobile.message}
|
||||
</p>
|
||||
)}
|
||||
</ShowcaseSection>
|
||||
|
||||
<ShowcaseSection title="Settings" className="grid grid-cols-1 gap-5">
|
||||
<Select
|
||||
{...register("language")}
|
||||
@@ -461,6 +365,7 @@ const CreateCompany = ({ defaultValues, editMode, id }: IProps) => {
|
||||
})}
|
||||
label="Street"
|
||||
name="address.street"
|
||||
required
|
||||
type="text"
|
||||
placeholder="Enter Street"
|
||||
/>
|
||||
@@ -482,6 +387,7 @@ const CreateCompany = ({ defaultValues, editMode, id }: IProps) => {
|
||||
},
|
||||
})}
|
||||
label="City"
|
||||
required
|
||||
name="address.city"
|
||||
type="text"
|
||||
placeholder="Enter City"
|
||||
@@ -506,6 +412,7 @@ const CreateCompany = ({ defaultValues, editMode, id }: IProps) => {
|
||||
label="State"
|
||||
name="address.state"
|
||||
type="text"
|
||||
required
|
||||
placeholder="Enter State"
|
||||
/>
|
||||
{errors.address?.state && (
|
||||
@@ -528,6 +435,7 @@ const CreateCompany = ({ defaultValues, editMode, id }: IProps) => {
|
||||
label="Postal code"
|
||||
name="address.postal_code"
|
||||
type="text"
|
||||
required
|
||||
placeholder="Enter Postal code"
|
||||
/>
|
||||
{errors.address?.postal_code && (
|
||||
@@ -550,6 +458,7 @@ const CreateCompany = ({ defaultValues, editMode, id }: IProps) => {
|
||||
label="Country"
|
||||
name="address.country"
|
||||
type="text"
|
||||
required
|
||||
placeholder="Enter Country"
|
||||
/>
|
||||
{errors.address?.country && (
|
||||
@@ -595,30 +504,6 @@ const CreateCompany = ({ defaultValues, editMode, id }: IProps) => {
|
||||
{errors.tags.specializations.message}
|
||||
</p>
|
||||
)}
|
||||
<InputGroup
|
||||
{...register("tags.certifications")}
|
||||
label="Certifications"
|
||||
name="tags.certifications"
|
||||
type="text"
|
||||
placeholder="Enter Tag Certifications"
|
||||
/>
|
||||
{errors.tags?.certifications && (
|
||||
<p className="mt-1 text-sm text-red-500">
|
||||
{errors.tags.certifications.message}
|
||||
</p>
|
||||
)}
|
||||
<InputGroup
|
||||
{...register("tags.cpv_codes")}
|
||||
label="CPV Code"
|
||||
name="tags.cpv_codes"
|
||||
type="text"
|
||||
placeholder="Enter Tag CPV Code"
|
||||
/>
|
||||
{errors.tags?.cpv_codes && (
|
||||
<p className="mt-1 text-sm text-red-500">
|
||||
{errors.tags.cpv_codes.message}
|
||||
</p>
|
||||
)}
|
||||
</ShowcaseSection>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -6,10 +6,9 @@ export function Logo() {
|
||||
src="/images/main-logo.svg"
|
||||
width={174}
|
||||
height={32}
|
||||
alt="NextAdmin logo"
|
||||
alt="Opp lens logo"
|
||||
role="presentation"
|
||||
quality={100}
|
||||
className="dark:invert"
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
import { cn } from "@/lib/utils";
|
||||
import { ReactNode } from "react";
|
||||
|
||||
interface IProps {
|
||||
status: string;
|
||||
children: ReactNode;
|
||||
}
|
||||
|
||||
const Status = ({ status, children }: IProps) => {
|
||||
const reds = [
|
||||
"cancelled",
|
||||
"inactive",
|
||||
"rejected",
|
||||
"failed",
|
||||
"denied",
|
||||
"blocked",
|
||||
];
|
||||
const greens = [
|
||||
"active",
|
||||
"approved",
|
||||
"completed",
|
||||
"success",
|
||||
"verified",
|
||||
"published",
|
||||
];
|
||||
const blues = ["awarded", "processing", "in-review", "scheduled"];
|
||||
const yellows = ["pending", "warning", "on-hold", "delayed"];
|
||||
const oranges = ["expired", "expiring", "limited"];
|
||||
const grays = ["draft", "disabled", "archived", "paused"];
|
||||
|
||||
return (
|
||||
<span
|
||||
className={cn("rounded-2xl px-3 py-1.5 text-sm font-medium capitalize", {
|
||||
"bg-green text-white": greens.includes(status),
|
||||
"bg-orange-light text-white": oranges.includes(status),
|
||||
"bg-error text-white": reds.includes(status),
|
||||
"bg-blue text-white": blues.includes(status),
|
||||
"bg-gray-3 text-gray-7": grays.includes(status),
|
||||
"bg-yellow-light text-yellow-dark-2": yellows.includes(status),
|
||||
"bg-green-light-6 text-green-dark": status === "new",
|
||||
"bg-blue-light-5 text-blue-dark": status === "info",
|
||||
"bg-error-light-6 text-error-dark": status === "urgent",
|
||||
"bg-primary text-white": status === "featured",
|
||||
})}
|
||||
>
|
||||
{children}
|
||||
</span>
|
||||
);
|
||||
};
|
||||
|
||||
export default Status;
|
||||
Reference in New Issue
Block a user