add new design (#70)

* add new design stuff

* add more ui things

* add more ui changes

* more ui changes

* add more design

* update emoji
This commit is contained in:
KM Koushik
2024-09-28 20:48:26 +10:00
committed by GitHub
parent 5ca6537a81
commit b75b125981
50 changed files with 1909 additions and 419 deletions

View File

@@ -10,22 +10,55 @@ import {
BreadcrumbSeparator,
} from "@unsend/ui/src/breadcrumb";
import Link from "next/link";
import { Button } from "@unsend/ui/src/button";
import { Plus } from "lucide-react";
import AddContact from "./add-contact";
import ContactList from "./contact-list";
import { TextWithCopyButton } from "@unsend/ui/src/text-with-copy";
import { formatDistanceToNow } from "date-fns";
import EmojiPicker, { Theme } from "emoji-picker-react";
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "@unsend/ui/src/popover";
import { Button } from "@unsend/ui/src/button";
import { useTheme } from "@unsend/ui";
export default function ContactsPage({
params,
}: {
params: { contactBookId: string };
}) {
const { theme } = useTheme();
const contactBookDetailQuery = api.contacts.getContactBookDetails.useQuery({
contactBookId: params.contactBookId,
});
const utils = api.useUtils();
const updateContactBookMutation = api.contacts.updateContactBook.useMutation({
onMutate: async (data) => {
await utils.contacts.getContactBookDetails.cancel();
utils.contacts.getContactBookDetails.setData(
{
contactBookId: params.contactBookId,
},
(old) => {
if (!old) return old;
return {
...old,
...data,
};
}
);
},
onSettled: () => {
utils.contacts.getContactBookDetails.invalidate({
contactBookId: params.contactBookId,
});
},
});
return (
<div>
<div className="flex justify-between items-center">
@@ -34,15 +67,51 @@ export default function ContactsPage({
<BreadcrumbList>
<BreadcrumbItem>
<BreadcrumbLink asChild>
<Link href="/contacts" className="text-lg">
<Link href="/contacts" className="text-xl">
Contact books
</Link>
</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator className="text-lg" />
<BreadcrumbSeparator className="text-xl" />
<BreadcrumbItem>
<BreadcrumbPage className="text-lg ">
{contactBookDetailQuery.data?.name}
<BreadcrumbPage className="text-xl">
<div className="flex items-center gap-2">
<span className="text-lg">
<Popover>
<PopoverTrigger asChild>
<Button
variant="ghost"
className="p-0 hover:bg-transparent text-lg"
type="button"
>
{contactBookDetailQuery.data?.emoji}
</Button>
</PopoverTrigger>
<PopoverContent className="w-full rounded-none border-0 !bg-transparent !p-0 shadow-none drop-shadow-md">
<EmojiPicker
onEmojiClick={(emojiObject) => {
// Handle emoji selection here
// You might want to update the contactBook's emoji
updateContactBookMutation.mutate({
contactBookId: params.contactBookId,
emoji: emojiObject.emoji,
});
}}
theme={
theme === "system"
? Theme.AUTO
: theme === "dark"
? Theme.DARK
: Theme.LIGHT
}
/>
</PopoverContent>
</Popover>
</span>
<span className="text-xl">
{contactBookDetailQuery.data?.name}
</span>
</div>
</BreadcrumbPage>
</BreadcrumbItem>
</BreadcrumbList>
@@ -53,38 +122,77 @@ export default function ContactsPage({
</div>
</div>
<div className="mt-16">
<div className="flex justify-between">
<div>
<div className=" text-muted-foreground">Total Contacts</div>
<div className="text-xl mt-3">
{contactBookDetailQuery.data?.totalContacts !== undefined
? contactBookDetailQuery.data?.totalContacts
: "--"}
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4 sm:gap-6 lg:gap-8">
<div className="flex flex-col gap-2 rounded-lg border p-4 shadow">
<p className="font-semibold mb-1">Metrics</p>
<div className="flex items-center gap-2">
<div className="text-muted-foreground w-[130px] text-sm">
Total Contacts
</div>
<div className="font-mono text-sm">
{contactBookDetailQuery.data?.totalContacts !== undefined
? contactBookDetailQuery.data?.totalContacts
: "--"}
</div>
</div>
<div className="flex items-center gap-2">
<div className="text-muted-foreground w-[130px] text-sm">
Unsubscribed
</div>
<div className="font-mono text-sm">
{contactBookDetailQuery.data?.unsubscribedContacts !== undefined
? contactBookDetailQuery.data?.unsubscribedContacts
: "--"}
</div>
</div>
</div>
<div>
<div className="text-muted-foreground">Unsubscribed</div>
<div className="text-xl mt-3">
{contactBookDetailQuery.data?.unsubscribedContacts !== undefined
? contactBookDetailQuery.data?.unsubscribedContacts
: "--"}
<div className="flex flex-col gap-2 rounded-lg border p-4 shadow">
<p className="font-semibold">Details</p>
<div className="flex items-center gap-2">
<div className="text-muted-foreground w-[130px] text-sm">
Contact book ID
</div>
<TextWithCopyButton
value={params.contactBookId}
alwaysShowCopy
className="text-sm w-[130px] overflow-hidden text-ellipsis font-mono"
/>
</div>
<div className="flex items-center gap-2">
<div className="text-muted-foreground w-[130px] text-sm">
Created at
</div>
<div className="text-sm">
{contactBookDetailQuery.data?.createdAt
? formatDistanceToNow(contactBookDetailQuery.data.createdAt, {
addSuffix: true,
})
: "--"}
</div>
</div>
</div>
<div>
<div className="text-muted-foreground">Created at</div>
<div className="text-xl mt-3">
{contactBookDetailQuery.data?.createdAt
? formatDistanceToNow(contactBookDetailQuery.data.createdAt, {
<div className="flex flex-col gap-2 rounded-lg border p-4 shadow">
<p className="font-semibold">Recent campaigns</p>
{!contactBookDetailQuery.isLoading &&
contactBookDetailQuery.data?.campaigns.length === 0 ? (
<div className="text-muted-foreground text-sm">
No campaigns yet.
</div>
) : null}
{contactBookDetailQuery.data?.campaigns.map((campaign) => (
<div key={campaign.id} className="flex items-center gap-2">
<Link href={`/campaigns/${campaign.id}`}>
<div className="text-sm hover:underline hover:decoration-dashed text-nowrap w-[200px] overflow-hidden text-ellipsis">
{campaign.name}
</div>
</Link>
<div className="text-muted-foreground text-xs">
{formatDistanceToNow(campaign.createdAt, {
addSuffix: true,
})
: "--"}
</div>
</div>
<div>
<div className="text-muted-foreground">Contact book id</div>
<div className="border mt-3 px-3 rounded bg-muted/30 ">
<TextWithCopyButton value={params.contactBookId} alwaysShowCopy />
</div>
})}
</div>
</div>
))}
</div>
</div>
<div className="mt-16">