Skip to content

Commit

Permalink
feat(resource): 🚸 added toast acknowledgement to notify user
Browse files Browse the repository at this point in the history
  • Loading branch information
vignesh-gupta committed May 19, 2024
1 parent 695f062 commit 5d6b354
Show file tree
Hide file tree
Showing 7 changed files with 51 additions and 24 deletions.
15 changes: 5 additions & 10 deletions app/(main)/projects/[id]/settings/danger-zone/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,10 @@ const ProjectSettingsDangerZonePage = ({
);
const router = useRouter();

const handleDeleteProject = () => {
deleteProject({ id })
.then(() => {
toast.success("Project deleted successfully");
router.push(DASHBOARD_ROUTE);
})
.catch(() => {
toast.error("Failed to delete project");
});
};
const handleDeleteProject = () =>
deleteProject({ id }).then(() => {
router.push(DASHBOARD_ROUTE);
});

return (
<div>
Expand All @@ -44,6 +38,7 @@ const ProjectSettingsDangerZonePage = ({
onConfirm={handleDeleteProject}
header="Delete project"
disabled={isPending}
toastMessage="Project deleted successfully"
>
<Button variant="destructive" disabled={isPending}>
Delete Project
Expand Down
9 changes: 7 additions & 2 deletions components/modals/confirm-modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,15 @@ import {
} from "@/components/ui/alert-dialog";
import { ReactNode } from "react";
import { buttonVariants } from "../ui/button";
import { toast } from "sonner";

type ConfirmModalProps = {
children: ReactNode;
disabled?: boolean;
onConfirm: () => void;
onConfirm: () => Promise<any>;
header: string;
description?: string;
toastMessage?: string;
};

const ConfirmModal = ({
Expand All @@ -25,9 +27,12 @@ const ConfirmModal = ({
disabled,
header,
onConfirm,
toastMessage = "Action completed successfully.",
}: ConfirmModalProps) => {
const handleConfirm = () => {
onConfirm();
onConfirm()
.then(() => toast.success(toastMessage))
.catch(() => toast.error("Failed to perform action. Please try again."));
};

return (
Expand Down
1 change: 1 addition & 0 deletions components/resources/file-card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ const FileCard = ({
header={`Delete file : ${title}`}
onConfirm={() => deleteFile({ _id })}
disabled={isDeleting}
toastMessage="File deleted successfully"
>
<Button size="icon" variant="ghost">
<Trash className="h-5 w-5" />
Expand Down
6 changes: 4 additions & 2 deletions components/resources/link-card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import { Id } from "@/convex/_generated/dataModel";
import useApiMutation from "@/lib/hooks/use-api-mutation";
import { useLinkModal } from "@/lib/store/use-link-modal";
import { Edit, LinkIcon, Trash } from "lucide-react";
import ConfirmModal from "@/components/modals/confirm-modal";
import { Avatar, AvatarFallback, AvatarImage } from "../ui/avatar";
import ConfirmModal from "../modals/confirm-modal";

type LinkCardProps = {
resource: {
Expand Down Expand Up @@ -45,7 +45,7 @@ const LinkCard = ({
className="font-medium hover:underline hover:text-gray-900 dark:hover:text-gray-50"
href={url}
>
{title}
{title.length > 10 ? `${title.slice(0, 10)}...` : title}
</a>
</div>
<div>
Expand All @@ -60,6 +60,8 @@ const LinkCard = ({
<ConfirmModal
onConfirm={() => deleteLink({ _id })}
header={`Delete link:${title}`}
disabled={isPending}
toastMessage="Link deleted successfully"
>
<Button size="icon" variant="ghost" disabled={isPending}>
<Trash className="h-5 w-5" />
Expand Down
3 changes: 2 additions & 1 deletion components/resources/resource-list.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,13 @@ const ResourceList = () => {
const files = useQuery(api.resources.files.list, {
projectId: param.id as Id<"projects">,
});

return (
<div className="grid grid-cols-2 md:grid-cols-5 gap-2">
<Card className="col-span-3 overflow-hidden">
<CardHeader className="bg-gray-100 dark:bg-gray-800 flex-row flex items-center justify-between py-3">
<h2 className="text-lg font-semibold">Files</h2>
<UploadFile />
<UploadFile fileCount={files?.length} />
</CardHeader>
<CardContent className="p-6 grid gap-6">
{files && files.length > 0 ? (
Expand Down
38 changes: 29 additions & 9 deletions components/resources/upload-file.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,14 @@ import { useUploadFiles } from "@xixixao/uploadstuff/react";
import { Upload } from "lucide-react";
import { useParams } from "next/navigation";
import { Button } from "../ui/button";
import { MAX_FILE_COUNT, MAX_FILE_SIZE } from "@/lib/constants";
import { toast } from "sonner";

const UploadFile = () => {
type UploadFileProps = {
fileCount?: number;
};

const UploadFile = ({ fileCount = 0 }: UploadFileProps) => {
const params = useParams();

const { mutate: generateUploadUrl, isPending } = useApiMutation(
Expand All @@ -23,18 +29,32 @@ const UploadFile = () => {
fileInput.accept = "*/*";

fileInput.addEventListener("change", async (e) => {
if (fileCount >= MAX_FILE_COUNT) {
toast.error(`A project can have a maximum of ${MAX_FILE_COUNT} files.`);
return;
}

const file = (e.target as HTMLInputElement).files?.[0];
if (!file) {
if (!file) return;

if (file.size > MAX_FILE_SIZE) {
toast.error("File size should be less than 5MB");
return;
}

const [res] = await startUpload([file]);
createFileResource({
title: res.name,
storageId: (res.response as { storageId: Id<"_storage"> }).storageId,
projectId: params.id as Id<"projects">,
type: res.type,
});
try {
const [res] = await startUpload([file]);
createFileResource({
title: res.name,
storageId: (res.response as { storageId: Id<"_storage"> }).storageId,
projectId: params.id as Id<"projects">,
type: res.type,
});

toast.success("File uploaded successfully.");
} catch (e) {
toast.error("Failed to upload file. Please try again.");
}
});

fileInput.click();
Expand Down
3 changes: 3 additions & 0 deletions lib/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ import { TaskPriority, TaskStatus, TaskType } from "./types";

export const DASHBOARD_ROUTE = "/dashboard";

export const MAX_FILE_SIZE = 1024 * 1024 * 5; // 5MB
export const MAX_FILE_COUNT = 10;

export const UNASSIGNED_USER = {
label: "Unassigned",
value: process.env.UNASSIGNED_USER_ID as Id<"users">,
Expand Down

0 comments on commit 5d6b354

Please sign in to comment.