fix colors in dashboard (#206)

This commit is contained in:
KM Koushik
2025-08-30 15:59:23 +10:00
committed by GitHub
parent f18a6b514b
commit 1869bf427c
24 changed files with 133 additions and 107 deletions

View File

@@ -146,35 +146,35 @@ export default function CampaignDetailsPage({
} }
const CampaignStatusBadge: React.FC<{ status: string }> = ({ status }) => { const CampaignStatusBadge: React.FC<{ status: string }> = ({ status }) => {
let outsideColor = "bg-gray-600"; let outsideColor = "bg-gray";
let insideColor = "bg-gray-600/50"; let insideColor = "bg-gray/50";
switch (status) { switch (status) {
case "delivered": case "delivered":
outsideColor = "bg-emerald-500/30"; outsideColor = "bg-green/30";
insideColor = "bg-emerald-500"; insideColor = "bg-green";
break; break;
case "bounced": case "bounced":
case "unsubscribed": case "unsubscribed":
outsideColor = "bg-red-500/30"; outsideColor = "bg-red/30";
insideColor = "bg-red-500"; insideColor = "bg-red";
break; break;
case "clicked": case "clicked":
outsideColor = "bg-cyan-500/30"; outsideColor = "bg-blue/30";
insideColor = "bg-cyan-500"; insideColor = "bg-blue";
break; break;
case "opened": case "opened":
outsideColor = "bg-indigo-500/30"; outsideColor = "bg-purple/30";
insideColor = "bg-indigo-500"; insideColor = "bg-purple";
break; break;
case "complained": case "complained":
outsideColor = "bg-yellow-500/30"; outsideColor = "bg-yellow/30";
insideColor = "bg-yellow-500"; insideColor = "bg-yellow";
break; break;
default: default:
outsideColor = "bg-gray-600/40"; outsideColor = "bg-gray/40";
insideColor = "bg-gray-600"; insideColor = "bg-gray";
} }
return ( return (

View File

@@ -103,10 +103,10 @@ export default function CampaignList() {
<div <div
className={`text-center w-[130px] rounded capitalize py-1 text-xs ${ className={`text-center w-[130px] rounded capitalize py-1 text-xs ${
campaign.status === CampaignStatus.DRAFT campaign.status === CampaignStatus.DRAFT
? "bg-gray-500/15 dark:bg-gray-400/15 text-gray-700 dark:text-gray-400/90 border border-gray-500/25 dark:border-gray-700/25" ? "bg-gray/15 text-gray border border-gray/25"
: campaign.status === CampaignStatus.SENT : campaign.status === CampaignStatus.SENT
? "bg-green-500/15 dark:bg-green-600/10 text-green-700 dark:text-green-600/90 border border-green-500/25 dark:border-green-700/25" ? "bg-green/15 text-green border border-green/25"
: "bg-yellow-500/15 dark:bg-yellow-600/10 text-yellow-700 dark:text-yellow-600/90 border border-yellow-500/25 dark:border-yellow-700/25" : "bg-yellow/15 text-yellow border border-yellow/25"
}`} }`}
> >
{campaign.status.toLowerCase()} {campaign.status.toLowerCase()}

View File

@@ -62,7 +62,7 @@ export const DeleteCampaign: React.FC<{
setOpen(false); setOpen(false);
toast.success(`Campaign deleted`); toast.success(`Campaign deleted`);
}, },
} },
); );
} }
@@ -75,7 +75,7 @@ export const DeleteCampaign: React.FC<{
> >
<DialogTrigger asChild> <DialogTrigger asChild>
<Button variant="ghost" size="sm" className="p-0 hover:bg-transparent"> <Button variant="ghost" size="sm" className="p-0 hover:bg-transparent">
<Trash2 className="h-[18px] w-[18px] text-red-600/80" /> <Trash2 className="h-[18px] w-[18px] text-red/80" />
</Button> </Button>
</DialogTrigger> </DialogTrigger>
<DialogContent> <DialogContent>

View File

@@ -35,7 +35,7 @@ export const DuplicateCampaign: React.FC<{
setOpen(false); setOpen(false);
toast.success(`Campaign duplicated`); toast.success(`Campaign duplicated`);
}, },
} },
); );
} }
@@ -46,7 +46,7 @@ export const DuplicateCampaign: React.FC<{
> >
<DialogTrigger asChild> <DialogTrigger asChild>
<Button variant="ghost" size="sm" className="p-0 hover:bg-transparent"> <Button variant="ghost" size="sm" className="p-0 hover:bg-transparent">
<Copy className="h-[18px] w-[18px] text-blue-600/80" /> <Copy className="h-[18px] w-[18px] text-blue/80" />
</Button> </Button>
</DialogTrigger> </DialogTrigger>
<DialogContent> <DialogContent>

View File

@@ -152,13 +152,13 @@ export default function ContactList({
</TableCell> </TableCell>
<TableCell> <TableCell>
{contact.subscribed ? ( {contact.subscribed ? (
<div className="text-center w-[130px] rounded capitalize py-1 text-xs bg-green-500/15 dark:bg-green-600/10 text-green-700 dark:text-green-600/90 border border-green-500/25 dark:border-green-700/25"> <div className="text-center w-[130px] rounded capitalize py-1 text-xs bg-green/15 text-green border border-green/25">
Subscribed Subscribed
</div> </div>
) : ( ) : (
<Tooltip> <Tooltip>
<TooltipTrigger> <TooltipTrigger>
<div className="text-center w-[130px] rounded capitalize py-1 text-xs bg-red-500/10 text-red-600 dark:text-red-700/90 border border-red-600/10"> <div className="text-center w-[130px] rounded capitalize py-1 text-xs bg-red/10 text-red border border-red/10">
Unsubscribed Unsubscribed
</div> </div>
</TooltipTrigger> </TooltipTrigger>
@@ -166,7 +166,7 @@ export default function ContactList({
<p> <p>
{getUnsubscribeReason( {getUnsubscribeReason(
contact.unsubscribeReason ?? contact.unsubscribeReason ??
UnsubscribeReason.UNSUBSCRIBED UnsubscribeReason.UNSUBSCRIBED,
)} )}
</p> </p>
</TooltipContent> </TooltipContent>

View File

@@ -66,7 +66,7 @@ export const DeleteContact: React.FC<{
onError: (e) => { onError: (e) => {
toast.error(`Contact not deleted: ${e.message}`); toast.error(`Contact not deleted: ${e.message}`);
}, },
} },
); );
} }
@@ -79,7 +79,7 @@ export const DeleteContact: React.FC<{
> >
<DialogTrigger asChild> <DialogTrigger asChild>
<Button variant="ghost" size="sm"> <Button variant="ghost" size="sm">
<Trash2 className="h-4 w-4 text-red-600/80" /> <Trash2 className="h-4 w-4 text-red/80" />
</Button> </Button>
</DialogTrigger> </DialogTrigger>
<DialogContent> <DialogContent>

View File

@@ -46,7 +46,7 @@ export const DeleteContactBook: React.FC<{
}); });
async function onContactBookDelete( async function onContactBookDelete(
values: z.infer<typeof contactBookSchema> values: z.infer<typeof contactBookSchema>,
) { ) {
if (values.name !== contactBook.name) { if (values.name !== contactBook.name) {
contactBookForm.setError("name", { contactBookForm.setError("name", {
@@ -65,7 +65,7 @@ export const DeleteContactBook: React.FC<{
setOpen(false); setOpen(false);
toast.success(`Contact book deleted`); toast.success(`Contact book deleted`);
}, },
} },
); );
} }
@@ -78,7 +78,7 @@ export const DeleteContactBook: React.FC<{
> >
<DialogTrigger asChild> <DialogTrigger asChild>
<Button variant="ghost" size="sm" className="p-0 hover:bg-transparent "> <Button variant="ghost" size="sm" className="p-0 hover:bg-transparent ">
<Trash2 className="h-[18px] w-[18px] text-red-600/80 hover:text-red-600/70" /> <Trash2 className="h-[18px] w-[18px] text-red/80 hover:text-red/70" />
</Button> </Button>
</DialogTrigger> </DialogTrigger>
<DialogContent> <DialogContent>

View File

@@ -15,7 +15,6 @@ import { EmailStatus } from "@prisma/client";
import { api } from "~/trpc/react"; import { api } from "~/trpc/react";
import Spinner from "@unsend/ui/src/spinner"; import Spinner from "@unsend/ui/src/spinner";
import { useTheme } from "@unsend/ui"; import { useTheme } from "@unsend/ui";
import { EMAIL_COLORS } from "~/lib/constants/colors";
import { useColors } from "./hooks/useColors"; import { useColors } from "./hooks/useColors";
interface EmailChartProps { interface EmailChartProps {
@@ -127,7 +126,10 @@ export default function EmailChart({ days, domain }: EmailChartProps) {
</p> </p>
{data.delivered ? ( {data.delivered ? (
<div className="flex gap-2 items-center"> <div className="flex gap-2 items-center">
<div className="w-2.5 h-2.5 bg-[#40a02bcc] dark:bg-[#a6e3a1] rounded-[2px]"></div> <div
className="w-2.5 h-2.5 rounded-[2px]"
style={{ backgroundColor: currentColors.delivered }}
></div>
<p className="text-xs text-muted-foreground w-[70px]"> <p className="text-xs text-muted-foreground w-[70px]">
Delivered Delivered
</p> </p>
@@ -136,7 +138,10 @@ export default function EmailChart({ days, domain }: EmailChartProps) {
) : null} ) : null}
{data.bounced ? ( {data.bounced ? (
<div className="flex gap-2 items-center"> <div className="flex gap-2 items-center">
<div className="w-2.5 h-2.5 bg-[#d20f39cc] dark:bg-[#f38ba8] rounded-[2px]"></div> <div
className="w-2.5 h-2.5 rounded-[2px]"
style={{ backgroundColor: currentColors.bounced }}
></div>
<p className="text-xs text-muted-foreground w-[70px]"> <p className="text-xs text-muted-foreground w-[70px]">
Bounced Bounced
</p> </p>
@@ -145,7 +150,12 @@ export default function EmailChart({ days, domain }: EmailChartProps) {
) : null} ) : null}
{data.complained ? ( {data.complained ? (
<div className="flex gap-2 items-center"> <div className="flex gap-2 items-center">
<div className="w-2.5 h-2.5 bg-[#df8e1dcc] dark:bg-[#F9E2AF] rounded-[2px]"></div> <div
className="w-2.5 h-2.5 rounded-[2px]"
style={{
backgroundColor: currentColors.complained,
}}
></div>
<p className="text-xs text-muted-foreground w-[70px]"> <p className="text-xs text-muted-foreground w-[70px]">
Complained Complained
</p> </p>
@@ -154,7 +164,10 @@ export default function EmailChart({ days, domain }: EmailChartProps) {
) : null} ) : null}
{data.opened ? ( {data.opened ? (
<div className="flex gap-2 items-center"> <div className="flex gap-2 items-center">
<div className="w-2.5 h-2.5 bg-[#8839efcc] dark:bg-[#cba6f7] rounded-[2px]"></div> <div
className="w-2.5 h-2.5 rounded-[2px]"
style={{ backgroundColor: currentColors.opened }}
></div>
<p className="text-xs text-muted-foreground w-[70px]"> <p className="text-xs text-muted-foreground w-[70px]">
Opened Opened
</p> </p>
@@ -163,7 +176,10 @@ export default function EmailChart({ days, domain }: EmailChartProps) {
) : null} ) : null}
{data.clicked ? ( {data.clicked ? (
<div className="flex gap-2 items-center"> <div className="flex gap-2 items-center">
<div className="w-2.5 h-2.5 bg-[#04a5e5cc] dark:bg-[#93c5fd] rounded-[2px]"></div> <div
className="w-2.5 h-2.5 rounded-[2px]"
style={{ backgroundColor: currentColors.clicked }}
></div>
<p className="text-xs text-muted-foreground w-[70px]"> <p className="text-xs text-muted-foreground w-[70px]">
Clicked Clicked
</p> </p>
@@ -236,16 +252,34 @@ const EmailChartItem: React.FC<DashboardItemCardProps> = ({
count, count,
percentage, percentage,
}) => { }) => {
const color = EMAIL_COLORS[status]; const currentColors = useColors();
const getColorForStatus = (status: EmailStatus | "total"): string => {
switch (status) {
case "DELIVERED":
return currentColors.delivered;
case "BOUNCED":
return currentColors.bounced;
case "COMPLAINED":
return currentColors.complained;
case "OPENED":
return currentColors.opened;
case "CLICKED":
return currentColors.clicked;
case "total":
default:
return "#6b7280"; // gray-500 for total and other statuses
}
};
return ( return (
<div className="flex gap-3 items-stretch font-mono"> <div className="flex gap-3 items-stretch font-mono">
{/* <div className={`${color} w-0.5 rounded-full`}></div> */}
<div> <div>
<div className=" flex items-center gap-2"> <div className=" flex items-center gap-2">
<div className={`${color} w-2.5 h-2.5 rounded-[3px]`}></div> <div
{/* <div className={`${color} w-0.5 rounded-full`}></div> */} className="w-2.5 h-2.5 rounded-[3px]"
style={{ backgroundColor: getColorForStatus(status) }}
></div>
<div className="text-xs uppercase text-muted-foreground "> <div className="text-xs uppercase text-muted-foreground ">
{status.toLowerCase()} {status.toLowerCase()}

View File

@@ -62,7 +62,7 @@ export default function AddApiKey() {
setApiKey(data); setApiKey(data);
apiKeyForm.reset(); apiKeyForm.reset();
}, },
} },
); );
} }
@@ -132,7 +132,7 @@ export default function AddApiKey() {
onClick={handleCopy} onClick={handleCopy}
> >
{isCopied ? ( {isCopied ? (
<CheckIcon className="h-4 w-4 text-green-500" /> <CheckIcon className="h-4 w-4 text-green" />
) : ( ) : (
<ClipboardCopy className="h-4 w-4" /> <ClipboardCopy className="h-4 w-4" />
)} )}

View File

@@ -62,7 +62,7 @@ export const DeleteApiKey: React.FC<{
setOpen(false); setOpen(false);
toast.success(`API key deleted`); toast.success(`API key deleted`);
}, },
} },
); );
} }
@@ -75,7 +75,7 @@ export const DeleteApiKey: React.FC<{
> >
<DialogTrigger asChild> <DialogTrigger asChild>
<Button variant="ghost" size="sm"> <Button variant="ghost" size="sm">
<Trash2 className="h-4 w-4 text-red-600/80" /> <Trash2 className="h-4 w-4 text-red/80" />
</Button> </Button>
</DialogTrigger> </DialogTrigger>
<DialogContent> <DialogContent>

View File

@@ -42,7 +42,7 @@ export default function DomainItemPage({
{ {
refetchInterval: (q) => (q?.state.data?.isVerifying ? 10000 : false), refetchInterval: (q) => (q?.state.data?.isVerifying ? 10000 : false),
refetchIntervalInBackground: true, refetchIntervalInBackground: true,
}, }
); );
const verifyQuery = api.domain.startVerification.useMutation(); const verifyQuery = api.domain.startVerification.useMutation();
@@ -54,7 +54,7 @@ export default function DomainItemPage({
onSettled: () => { onSettled: () => {
domainQuery.refetch(); domainQuery.refetch();
}, },
}, }
); );
}; };
@@ -232,7 +232,7 @@ const DomainSettings: React.FC<{ domain: Domain }> = ({ domain }) => {
const utils = api.useUtils(); const utils = api.useUtils();
const [clickTracking, setClickTracking] = React.useState( const [clickTracking, setClickTracking] = React.useState(
domain.clickTracking, domain.clickTracking
); );
const [openTracking, setOpenTracking] = React.useState(domain.openTracking); const [openTracking, setOpenTracking] = React.useState(domain.openTracking);
@@ -245,7 +245,7 @@ const DomainSettings: React.FC<{ domain: Domain }> = ({ domain }) => {
utils.domain.invalidate(); utils.domain.invalidate();
toast.success("Click tracking updated"); toast.success("Click tracking updated");
}, },
}, }
); );
} }
@@ -258,7 +258,7 @@ const DomainSettings: React.FC<{ domain: Domain }> = ({ domain }) => {
utils.domain.invalidate(); utils.domain.invalidate();
toast.success("Open tracking updated"); toast.success("Open tracking updated");
}, },
}, }
); );
} }
return ( return (
@@ -303,24 +303,20 @@ const DomainSettings: React.FC<{ domain: Domain }> = ({ domain }) => {
}; };
const DnsVerificationStatus: React.FC<{ status: string }> = ({ status }) => { const DnsVerificationStatus: React.FC<{ status: string }> = ({ status }) => {
let badgeColor = "bg-gray-400/10 text-gray-500 border-gray-400/10"; // Default color let badgeColor = "bg-gray/10 text-gray border-gray/10"; // Default color
switch (status) { switch (status) {
case DomainStatus.SUCCESS: case DomainStatus.SUCCESS:
badgeColor = badgeColor = "bg-green/15 text-green border border-green/25";
"bg-green-500/15 dark:bg-green-600/10 text-green-700 dark:text-green-600/90 border border-green-500/25 dark:border-green-700/25";
break; break;
case DomainStatus.FAILED: case DomainStatus.FAILED:
badgeColor = badgeColor = "bg-red/10 text-red border border-red/10";
"bg-red-500/10 text-red-600 dark:text-red-700/90 border border-red-600/10";
break; break;
case DomainStatus.TEMPORARY_FAILURE: case DomainStatus.TEMPORARY_FAILURE:
case DomainStatus.PENDING: case DomainStatus.PENDING:
badgeColor = badgeColor = "bg-yellow/20 text-yellow border border-yellow/10";
"bg-yellow-500/20 dark:bg-yellow-500/10 text-yellow-600 border border-yellow-600/10";
break; break;
default: default:
badgeColor = badgeColor = "bg-gray/10 text-gray border border-gray/20";
"bg-gray-200/70 dark:bg-gray-400/10 text-gray-600 dark:text-gray-400 border border-gray-300 dark:border-gray-400/20";
} }
return ( return (

View File

@@ -3,24 +3,20 @@ import { DomainStatus } from "@prisma/client";
export const DomainStatusBadge: React.FC<{ status: DomainStatus }> = ({ export const DomainStatusBadge: React.FC<{ status: DomainStatus }> = ({
status, status,
}) => { }) => {
let badgeColor = "bg-gray-400/10 text-gray-500 border-gray-400/10"; // Default color let badgeColor = "bg-gray/10 text-gray border-gray/10"; // Default color
switch (status) { switch (status) {
case DomainStatus.SUCCESS: case DomainStatus.SUCCESS:
badgeColor = badgeColor = "bg-green/15 text-green border border-green/25";
"bg-green-500/15 dark:bg-green-600/10 text-green-700 dark:text-green-600/90 border border-green-500/25 dark:border-green-700/25";
break; break;
case DomainStatus.FAILED: case DomainStatus.FAILED:
badgeColor = badgeColor = "bg-red/10 text-red border border-red/10";
"bg-red-500/10 text-red-600 dark:text-red-700/90 border border-red-600/10";
break; break;
case DomainStatus.TEMPORARY_FAILURE: case DomainStatus.TEMPORARY_FAILURE:
case DomainStatus.PENDING: case DomainStatus.PENDING:
badgeColor = badgeColor = "bg-yellow/20 text-yellow border border-yellow/10";
"bg-yellow-500/20 dark:bg-yellow-500/10 text-yellow-600 border border-yellow-600/10";
break; break;
default: default:
badgeColor = badgeColor = "bg-gray/70 text-gray border border-gray/20";
"bg-gray-200/70 dark:bg-gray-400/10 text-gray-600 dark:text-gray-400 border border-gray-300 dark:border-gray-400/20";
} }
return ( return (

View File

@@ -3,23 +3,23 @@ import { DomainStatus } from "@prisma/client";
export const StatusIndicator: React.FC<{ status: DomainStatus }> = ({ export const StatusIndicator: React.FC<{ status: DomainStatus }> = ({
status, status,
}) => { }) => {
let badgeColor = "bg-gray-400"; // Default color let badgeColor = "bg-gray"; // Default color
switch (status) { switch (status) {
case DomainStatus.NOT_STARTED: case DomainStatus.NOT_STARTED:
badgeColor = "bg-gray-400"; badgeColor = "bg-gray";
break; break;
case DomainStatus.SUCCESS: case DomainStatus.SUCCESS:
badgeColor = "bg-emerald-500"; badgeColor = "bg-green";
break; break;
case DomainStatus.FAILED: case DomainStatus.FAILED:
badgeColor = "bg-red-500"; badgeColor = "bg-red";
break; break;
case DomainStatus.TEMPORARY_FAILURE: case DomainStatus.TEMPORARY_FAILURE:
case DomainStatus.PENDING: case DomainStatus.PENDING:
badgeColor = "bg-yellow-500"; badgeColor = "bg-yellow";
break; break;
default: default:
badgeColor = "bg-gray-400"; badgeColor = "bg-gray";
} }
return <div className={` w-[2px] ${badgeColor} my-1.5 rounded-full`}></div>; return <div className={` w-[2px] ${badgeColor} my-1.5 rounded-full`}></div>;

View File

@@ -64,7 +64,7 @@ export const CancelEmail: React.FC<{
onError: (e) => { onError: (e) => {
toast.error(`Error cancelling email: ${e.message}`); toast.error(`Error cancelling email: ${e.message}`);
}, },
} },
); );
} }
@@ -77,7 +77,7 @@ export const CancelEmail: React.FC<{
> >
<DialogTrigger asChild> <DialogTrigger asChild>
<Button variant="ghost" size="sm"> <Button variant="ghost" size="sm">
<Trash2 className="h-4 w-4 text-red-500" /> <Trash2 className="h-4 w-4 text-red" />
</Button> </Button>
</DialogTrigger> </DialogTrigger>
<DialogContent> <DialogContent>

View File

@@ -46,12 +46,12 @@ import { SheetTitle, SheetDescription } from "@unsend/ui/src/sheet";
/* Stupid hydrating error. And I so stupid to understand the stupid NextJS docs */ /* Stupid hydrating error. And I so stupid to understand the stupid NextJS docs */
const DynamicSheetWithNoSSR = dynamic( const DynamicSheetWithNoSSR = dynamic(
() => import("@unsend/ui/src/sheet").then((mod) => mod.Sheet), () => import("@unsend/ui/src/sheet").then((mod) => mod.Sheet),
{ ssr: false } { ssr: false },
); );
const DynamicSheetContentWithNoSSR = dynamic( const DynamicSheetContentWithNoSSR = dynamic(
() => import("@unsend/ui/src/sheet").then((mod) => mod.SheetContent), () => import("@unsend/ui/src/sheet").then((mod) => mod.SheetContent),
{ ssr: false } { ssr: false },
); );
export default function EmailsList() { export default function EmailsList() {
@@ -231,7 +231,7 @@ export default function EmailsList() {
Scheduled at{" "} Scheduled at{" "}
{formatDate( {formatDate(
email.scheduledAt, email.scheduledAt,
"MMM dd'th', hh:mm a" "MMM dd'th', hh:mm a",
)} )}
</TooltipContent> </TooltipContent>
</Tooltip> </Tooltip>
@@ -247,7 +247,7 @@ export default function EmailsList() {
{email.latestStatus !== "SCHEDULED" {email.latestStatus !== "SCHEDULED"
? formatDate( ? formatDate(
email.scheduledAt ?? email.createdAt, email.scheduledAt ?? email.createdAt,
"MMM do, hh:mm a" "MMM do, hh:mm a",
) )
: "--"} : "--"}
</TableCell> </TableCell>
@@ -301,39 +301,39 @@ const EmailIcon: React.FC<{ status: EmailStatus }> = ({ status }) => {
case "SENT": case "SENT":
return ( return (
// <div className="border border-gray-400/60 p-2 rounded-lg bg-gray-400/10"> // <div className="border border-gray-400/60 p-2 rounded-lg bg-gray-400/10">
<Mail className="w-6 h-6 text-gray-500 " /> <Mail className="w-6 h-6 text-gray" />
// </div> // </div>
); );
case "DELIVERED": case "DELIVERED":
return ( return (
// <div className="border border-emerald-600/60 p-2 rounded-lg bg-emerald-500/10"> // <div className="border border-emerald-600/60 p-2 rounded-lg bg-emerald-500/10">
<MailCheck className="w-6 h-6 text-emerald-800" /> <MailCheck className="w-6 h-6 text-green" />
// </div> // </div>
); );
case "BOUNCED": case "BOUNCED":
case "FAILED": case "FAILED":
return ( return (
// <div className="border border-red-600/60 p-2 rounded-lg bg-red-500/10"> // <div className="border border-red-600/60 p-2 rounded-lg bg-red-500/10">
<MailX className="w-6 h-6 text-red-900" /> <MailX className="w-6 h-6 text-red" />
// </div> // </div>
); );
case "CLICKED": case "CLICKED":
return ( return (
// <div className="border border-cyan-600/60 p-2 rounded-lg bg-cyan-500/10"> // <div className="border border-cyan-600/60 p-2 rounded-lg bg-cyan-500/10">
<MailSearch className="w-6 h-6 text-cyan-700" /> <MailSearch className="w-6 h-6 text-blue" />
// </div> // </div>
); );
case "OPENED": case "OPENED":
return ( return (
// <div className="border border-indigo-600/60 p-2 rounded-lg bg-indigo-500/10"> // <div className="border border-indigo-600/60 p-2 rounded-lg bg-indigo-500/10">
<MailOpen className="w-6 h-6 text-indigo-700" /> <MailOpen className="w-6 h-6 text-purple" />
// </div> // </div>
); );
case "DELIVERY_DELAYED": case "DELIVERY_DELAYED":
case "COMPLAINED": case "COMPLAINED":
return ( return (
// <div className="border border-yellow-600/60 p-2 rounded-lg bg-yellow-500/10"> // <div className="border border-yellow-600/60 p-2 rounded-lg bg-yellow-500/10">
<MailWarning className="w-6 h-6 text-yellow-700" /> <MailWarning className="w-6 h-6 text-yellow" />
// </div> // </div>
); );
default: default:

View File

@@ -37,7 +37,7 @@ function VerifySuccess() {
return ( return (
<div> <div>
<div className="flex gap-2 items-center"> <div className="flex gap-2 items-center">
<CheckCircle2 className="h-4 w-4 text-green-500 flex-shrink-0" /> <CheckCircle2 className="h-4 w-4 text-green flex-shrink-0" />
<p>Your account has been upgraded to the paid plan.</p> <p>Your account has been upgraded to the paid plan.</p>
</div> </div>
<Link href="/settings/billing" className="mt-8"> <Link href="/settings/billing" className="mt-8">

View File

@@ -36,7 +36,7 @@ export const DeleteTeamInvite: React.FC<{
onError: async (error) => { onError: async (error) => {
toast.error(error.message); toast.error(error.message);
}, },
} },
); );
} }
@@ -47,7 +47,7 @@ export const DeleteTeamInvite: React.FC<{
> >
<DialogTrigger asChild> <DialogTrigger asChild>
<Button variant="ghost" size="sm"> <Button variant="ghost" size="sm">
<Trash2 className="h-4 w-4 text-red-600/80" /> <Trash2 className="h-4 w-4 text-red/80" />
</Button> </Button>
</DialogTrigger> </DialogTrigger>
<DialogContent> <DialogContent>

View File

@@ -38,7 +38,7 @@ export const DeleteTeamMember: React.FC<{
onError: async (error) => { onError: async (error) => {
toast.error(error.message); toast.error(error.message);
}, },
} },
); );
} }
@@ -50,9 +50,9 @@ export const DeleteTeamMember: React.FC<{
<DialogTrigger asChild> <DialogTrigger asChild>
<Button variant="ghost" size="sm"> <Button variant="ghost" size="sm">
{self ? ( {self ? (
<LogOut className="h-4 w-4 text-red-600/80" /> <LogOut className="h-4 w-4 text-red/80" />
) : ( ) : (
<Trash2 className="h-4 w-4 text-red-600/80" /> <Trash2 className="h-4 w-4 text-red/80" />
)} )}
</Button> </Button>
</DialogTrigger> </DialogTrigger>

View File

@@ -67,7 +67,7 @@ export default function TeamMembersList() {
</div> </div>
</TableCell> </TableCell>
<TableCell> <TableCell>
<div className="text-center w-[100px] rounded capitalize py-1 text-xs bg-green-500/15 dark:bg-green-600/10 text-green-700 dark:text-green-600/90 border border-green-500/25 dark:border-green-700/25"> <div className="text-center w-[100px] rounded capitalize py-1 text-xs bg-green/15 text-green border border-green/25">
Active Active
</div> </div>
</TableCell> </TableCell>
@@ -122,7 +122,7 @@ export default function TeamMembersList() {
</div> </div>
</TableCell> </TableCell>
<TableCell> <TableCell>
<div className="text-center w-[100px] rounded capitalize py-1 text-xs bg-yellow-500/15 dark:bg-yellow-600/10 text-yellow-700 dark:text-yellow-600/90 border border-yellow-500/25 dark:border-yellow-700/25"> <div className="text-center w-[100px] rounded capitalize py-1 text-xs bg-yellow/15 text-yellow border border-yellow/25">
Pending Pending
</div> </div>
</TableCell> </TableCell>

View File

@@ -29,7 +29,7 @@ export default function EditTemplatePage({
{ templateId: templateId }, { templateId: templateId },
{ {
enabled: !!templateId, enabled: !!templateId,
} },
); );
if (isLoading) { if (isLoading) {
@@ -63,7 +63,7 @@ function TemplateEditor({
const utils = api.useUtils(); const utils = api.useUtils();
const [json, setJson] = useState<Record<string, any> | undefined>( const [json, setJson] = useState<Record<string, any> | undefined>(
template.content ? JSON.parse(template.content) : undefined template.content ? JSON.parse(template.content) : undefined,
); );
const [isSaving, setIsSaving] = useState(false); const [isSaving, setIsSaving] = useState(false);
const [name, setName] = useState(template.name); const [name, setName] = useState(template.name);
@@ -86,13 +86,13 @@ function TemplateEditor({
const deboucedUpdateTemplate = useDebouncedCallback( const deboucedUpdateTemplate = useDebouncedCallback(
updateEditorContent, updateEditorContent,
1000 1000,
); );
const handleFileChange = async (file: File) => { const handleFileChange = async (file: File) => {
if (file.size > IMAGE_SIZE_LIMIT) { if (file.size > IMAGE_SIZE_LIMIT) {
throw new Error( throw new Error(
`File should be less than ${IMAGE_SIZE_LIMIT / 1024 / 1024}MB` `File should be less than ${IMAGE_SIZE_LIMIT / 1024 / 1024}MB`,
); );
} }
@@ -143,7 +143,7 @@ function TemplateEditor({
toast.error(`${e.message}. Reverting changes.`); toast.error(`${e.message}. Reverting changes.`);
setName(template.name); setName(template.name);
}, },
} },
); );
}} }}
/> />
@@ -152,9 +152,9 @@ function TemplateEditor({
<div className="flex items-center gap-4"> <div className="flex items-center gap-4">
<div className="flex items-center gap-2 text-sm text-gray-500"> <div className="flex items-center gap-2 text-sm text-gray-500">
{isSaving ? ( {isSaving ? (
<div className="h-2 w-2 bg-yellow-500 rounded-full" /> <div className="h-2 w-2 bg-yellow rounded-full" />
) : ( ) : (
<div className="h-2 w-2 bg-emerald-500 rounded-full" /> <div className="h-2 w-2 bg-green rounded-full" />
)} )}
{formatDistanceToNow(template.updatedAt) === "less than a minute" {formatDistanceToNow(template.updatedAt) === "less than a minute"
? "just now" ? "just now"
@@ -188,7 +188,7 @@ function TemplateEditor({
toast.error(`${e.message}. Reverting changes.`); toast.error(`${e.message}. Reverting changes.`);
setSubject(template.subject); setSubject(template.subject);
}, },
} },
); );
}} }}
className="mt-1 py-1 text-sm block w-full outline-none border-b border-transparent focus:border-border bg-transparent" className="mt-1 py-1 text-sm block w-full outline-none border-b border-transparent focus:border-border bg-transparent"

View File

@@ -62,7 +62,7 @@ export const DeleteTemplate: React.FC<{
setOpen(false); setOpen(false);
toast.success(`Template deleted`); toast.success(`Template deleted`);
}, },
} },
); );
} }
@@ -75,7 +75,7 @@ export const DeleteTemplate: React.FC<{
> >
<DialogTrigger asChild> <DialogTrigger asChild>
<Button variant="ghost" size="sm" className="p-0 hover:bg-transparent"> <Button variant="ghost" size="sm" className="p-0 hover:bg-transparent">
<Trash2 className="h-[18px] w-[18px] text-red-600/80" /> <Trash2 className="h-[18px] w-[18px] text-red/80" />
</Button> </Button>
</DialogTrigger> </DialogTrigger>
<DialogContent> <DialogContent>

View File

@@ -35,7 +35,7 @@ export const DuplicateTemplate: React.FC<{
setOpen(false); setOpen(false);
toast.success(`Template duplicated`); toast.success(`Template duplicated`);
}, },
} },
); );
} }
@@ -46,7 +46,7 @@ export const DuplicateTemplate: React.FC<{
> >
<DialogTrigger asChild> <DialogTrigger asChild>
<Button variant="ghost" size="sm" className="p-0 hover:bg-transparent"> <Button variant="ghost" size="sm" className="p-0 hover:bg-transparent">
<Copy className="h-[18px] w-[18px] text-blue-600/80" /> <Copy className="h-[18px] w-[18px] text-blue/80" />
</Button> </Button>
</DialogTrigger> </DialogTrigger>
<DialogContent> <DialogContent>

View File

@@ -36,7 +36,7 @@ export const PlanDetails = () => {
<ul className="mt-4 space-y-3"> <ul className="mt-4 space-y-3">
{perks.map((perk, index) => ( {perks.map((perk, index) => (
<li key={index} className="flex items-center gap-2"> <li key={index} className="flex items-center gap-2">
<CheckCircle2 className="h-4 w-4 text-green-500 flex-shrink-0" /> <CheckCircle2 className="h-4 w-4 text-green flex-shrink-0" />
<span className="text-sm">{perk}</span> <span className="text-sm">{perk}</span>
</li> </li>
))} ))}

View File

@@ -52,7 +52,7 @@ export const UpgradeModal = () => {
<ul className="space-y-2"> <ul className="space-y-2">
{basicPlanPerks.map((perk, index) => ( {basicPlanPerks.map((perk, index) => (
<li key={index} className="flex items-start gap-2"> <li key={index} className="flex items-start gap-2">
<CheckCircle2 className="h-4 w-4 text-green-500 flex-shrink-0 mt-0.5" /> <CheckCircle2 className="h-4 w-4 text-green flex-shrink-0 mt-0.5" />
<span className="text-sm">{perk}</span> <span className="text-sm">{perk}</span>
</li> </li>
))} ))}