119 lines
2.9 KiB
TypeScript
119 lines
2.9 KiB
TypeScript
"use client";
|
|
import React from "react";
|
|
import {
|
|
Drawer,
|
|
DrawerClose,
|
|
DrawerContent,
|
|
DrawerFooter,
|
|
DrawerHeader,
|
|
DrawerTitle,
|
|
DrawerTrigger,
|
|
} from "@/components/ui/drawer";
|
|
import { Button } from "@/components/ui/button";
|
|
import { api } from "@/trpc/react";
|
|
import { Input } from "@/components/ui/input";
|
|
import { useDebounce } from "use-debounce";
|
|
import { Skeleton } from "@/components/ui/skeleton";
|
|
import { toast } from "sonner";
|
|
import UserCard from "../user-card";
|
|
import type { User } from "@/server/db/schema";
|
|
|
|
const SearchResultCard = ({
|
|
addFriend,
|
|
user,
|
|
pending,
|
|
}: {
|
|
addFriend: (userId: string) => void;
|
|
pending: boolean;
|
|
user: User;
|
|
}) => {
|
|
return (
|
|
<UserCard user={user}>
|
|
<Button
|
|
size={"sm"}
|
|
className="ml-auto"
|
|
variant={"outline"}
|
|
disabled={pending}
|
|
onClick={() => {
|
|
if (!pending) addFriend(user.id!);
|
|
}}
|
|
>
|
|
{pending ? "Pending" : "Add Friend"}
|
|
</Button>
|
|
</UserCard>
|
|
);
|
|
};
|
|
|
|
export default function AddFriendDrawer() {
|
|
const utils = api.useUtils();
|
|
const [open, setOpen] = React.useState(false);
|
|
const [value, setValue] = React.useState("");
|
|
const [searchValue] = useDebounce(value, 1000);
|
|
|
|
const { data: searchResult, isFetching } = api.friend.search.useQuery(
|
|
{
|
|
search: searchValue,
|
|
},
|
|
{
|
|
enabled: !!searchValue,
|
|
}
|
|
);
|
|
const addFriend = api.friend.add.useMutation({
|
|
onSuccess() {
|
|
toast.success("Friend request sent!");
|
|
setOpen(false);
|
|
setValue("");
|
|
utils.friend.getAll.invalidate();
|
|
},
|
|
});
|
|
|
|
const handleAddFriend = (userId: string) => {
|
|
addFriend.mutate({
|
|
userId,
|
|
});
|
|
};
|
|
|
|
return (
|
|
<Drawer open={open} onOpenChange={setOpen}>
|
|
<DrawerTrigger asChild>
|
|
<Button size={"sm"}>Add Friend</Button>
|
|
</DrawerTrigger>
|
|
<DrawerContent>
|
|
<DrawerHeader>
|
|
<DrawerTitle>Add a friend</DrawerTitle>
|
|
</DrawerHeader>
|
|
<div className="px-4 space-y-4">
|
|
<Input
|
|
autoFocus
|
|
value={value}
|
|
onChange={(e) => setValue(e.currentTarget.value)}
|
|
placeholder="Search for a friend"
|
|
/>
|
|
<ul>
|
|
{isFetching ? (
|
|
<Skeleton className="h-6 w-full" />
|
|
) : searchResult?.length ? (
|
|
searchResult.map((res) => (
|
|
<li key={res.user.id}>
|
|
<SearchResultCard addFriend={handleAddFriend} {...res} />
|
|
</li>
|
|
))
|
|
) : (
|
|
<p className="text-muted-foreground text-sm">
|
|
{searchValue.length
|
|
? "No results found"
|
|
: "Start typing to search for a friend"}
|
|
</p>
|
|
)}
|
|
</ul>
|
|
</div>
|
|
<DrawerFooter>
|
|
<DrawerClose asChild>
|
|
<Button variant="outline">Cancel</Button>
|
|
</DrawerClose>
|
|
</DrawerFooter>
|
|
</DrawerContent>
|
|
</Drawer>
|
|
);
|
|
}
|