more modals replaced

This commit is contained in:
daniel31x13
2023-12-01 14:00:52 -05:00
parent 2c9541734a
commit a3c6d9b42e
13 changed files with 266 additions and 100 deletions
+5 -11
View File
@@ -12,23 +12,17 @@ type Props = {
export default function Checkbox({ label, state, className, onClick }: Props) {
return (
<label
className={`cursor-pointer flex items-center gap-2 ${className || ""}`}
className={`label cursor-pointer flex gap-2 justify-start ${
className || ""
}`}
>
<input
type="checkbox"
checked={state}
onChange={onClick}
className="peer sr-only"
className="checkbox checkbox-primary"
/>
<FontAwesomeIcon
icon={faSquareCheck}
className="w-5 h-5 text-primary peer-checked:block hidden"
/>
<FontAwesomeIcon
icon={faSquare}
className="w-5 h-5 text-primary peer-checked:hidden block"
/>
<span className="rounded select-none">{label}</span>
<span className="label-text">{label}</span>
</label>
);
}
+10 -10
View File
@@ -12,6 +12,7 @@ import getPublicUserData from "@/lib/client/getPublicUserData";
import useAccountStore from "@/store/account";
import EditCollectionModal from "./Modals/EditCollectionModal";
import EditCollectionSharingModal from "./Modals/EditCollectionSharingModal";
import DeleteCollectionModal from "./Modals/DeleteCollectionModal";
type Props = {
collection: CollectionIncludingMembersAndLinkCount;
@@ -62,6 +63,7 @@ export default function CollectionCard({ collection, className }: Props) {
const [editCollectionModal, setEditCollectionModal] = useState(false);
const [editCollectionSharingModal, setEditCollectionSharingModal] =
useState(false);
const [deleteCollectionModal, setDeleteCollectionModal] = useState(false);
return (
<div className="relative">
@@ -109,15 +111,7 @@ export default function CollectionCard({ collection, className }: Props) {
tabIndex={0}
onClick={() => {
(document?.activeElement as HTMLElement)?.blur();
collection &&
setModal({
modal: "COLLECTION",
state: true,
method: "UPDATE",
isOwner: permissions === true,
active: collection,
defaultIndex: permissions === true ? 2 : 1,
});
setDeleteCollectionModal(true);
}}
>
{permissions === true ? "Delete Collection" : "Leave Collection"}
@@ -132,7 +126,7 @@ export default function CollectionCard({ collection, className }: Props) {
{collectionOwner.id ? (
<ProfilePhoto
src={collectionOwner.image || undefined}
className="w-7 h-7"
dimensionClass="w-7 h-7"
/>
) : undefined}
{collection.members
@@ -212,6 +206,12 @@ export default function CollectionCard({ collection, className }: Props) {
modalId={"edit-collection-sharing-modal" + collection.id}
activeCollection={collection}
/>
<DeleteCollectionModal
isOpen={deleteCollectionModal}
onClose={() => setDeleteCollectionModal(false)}
modalId={"delete-collection-modal" + collection.id}
activeCollection={collection}
/>
</div>
);
}
+180
View File
@@ -0,0 +1,180 @@
import React, { useEffect, useState } from "react";
import TextInput from "@/components/TextInput";
import useCollectionStore from "@/store/collections";
import toast, { Toaster } from "react-hot-toast";
import {
faFolder,
faRightFromBracket,
faTrashCan,
} from "@fortawesome/free-solid-svg-icons";
import { HexColorPicker } from "react-colorful";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { CollectionIncludingMembersAndLinkCount } from "@/types/global";
import { useRouter } from "next/router";
import usePermissions from "@/hooks/usePermissions";
type Props = {
modalId: string;
isOpen: boolean;
onClose: Function;
activeCollection: CollectionIncludingMembersAndLinkCount;
};
export default function DeleteCollectionModal({
modalId,
isOpen,
onClose,
activeCollection,
}: Props) {
const modal = document.getElementById(modalId);
useEffect(() => {
modal?.addEventListener("close", () => {
onClose();
});
return () => {
modal?.addEventListener("close", () => {
onClose();
});
};
}, [isOpen]);
const [collection, setCollection] =
useState<CollectionIncludingMembersAndLinkCount>(activeCollection);
useEffect(() => {
setCollection(activeCollection);
setInputField("");
}, [isOpen]);
const [submitLoader, setSubmitLoader] = useState(false);
const { removeCollection } = useCollectionStore();
const router = useRouter();
const [inputField, setInputField] = useState("");
const permissions = usePermissions(collection.id as number);
const submit = async () => {
if (permissions === true) if (collection.name !== inputField) return null;
if (!submitLoader) {
setSubmitLoader(true);
if (!collection) return null;
setSubmitLoader(true);
const load = toast.loading("Deleting...");
let response;
response = await removeCollection(collection.id as any);
toast.dismiss(load);
if (response.ok) {
toast.success(`Deleted.`);
(document.getElementById(modalId) as any).close();
router.push("/collections");
} else toast.error(response.data as string);
setSubmitLoader(false);
}
};
return (
<dialog
id={modalId}
className="modal backdrop-blur-sm overflow-y-auto"
open={isOpen}
>
<Toaster
position="top-center"
reverseOrder={false}
toastOptions={{
className:
"border border-sky-100 dark:border-neutral-700 dark:bg-neutral-900 dark:text-white",
}}
/>
<div className="modal-box max-h-full overflow-y-visible border border-neutral-content w-11/12 max-w-2xl">
<form method="dialog">
<button className="btn btn-sm outline-none btn-circle btn-ghost absolute right-3 top-3">
</button>
</form>
<p className="text-xl mb-5 font-thin text-red-500">
{permissions === true ? "Delete" : "Leave"} Collection
</p>
<div className="flex flex-col gap-3">
{permissions === true ? (
<>
<div className="flex flex-col gap-3">
<p>
To confirm, type &quot;
<span className="font-bold">{collection.name}</span>
&quot; in the box below:
</p>
<TextInput
value={inputField}
onChange={(e) => setInputField(e.target.value)}
placeholder={`Type "${collection.name}" Here.`}
className="w-3/4 mx-auto"
/>
</div>
<div role="alert" className="alert alert-warning">
<svg
xmlns="http://www.w3.org/2000/svg"
className="stroke-current shrink-0 h-6 w-6"
fill="none"
viewBox="0 0 24 24"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"
/>
</svg>
<span>
<b>
Warning: Deleting this collection will permanently erase all
its contents
</b>
, and it will become inaccessible to everyone, including
members with previous access.
</span>
</div>
</>
) : (
<p>Click the button below to leave the current collection.</p>
)}
<button
disabled={permissions === true && inputField !== collection.name}
className={`ml-auto btn w-fit text-white flex items-center gap-2 duration-100 ${
permissions === true
? inputField === collection.name
? "bg-red-500 hover:bg-red-400 hover:dark:bg-red-600 cursor-pointer"
: "cursor-not-allowed bg-red-300 dark:bg-red-900"
: "bg-red-500 hover:bg-red-400 hover:dark:bg-red-600 cursor-pointer"
}`}
onClick={submit}
>
<FontAwesomeIcon
icon={permissions === true ? faTrashCan : faRightFromBracket}
className="h-5"
/>
{permissions === true ? "Delete" : "Leave"} Collection
</button>
</div>
</div>
<form method="dialog" className="modal-backdrop">
<button>close</button>
</form>
</dialog>
);
}
@@ -4,7 +4,6 @@ import useCollectionStore from "@/store/collections";
import toast, { Toaster } from "react-hot-toast";
import { faFolder } from "@fortawesome/free-solid-svg-icons";
import { HexColorPicker } from "react-colorful";
import { Collection } from "@prisma/client";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { CollectionIncludingMembersAndLinkCount } from "@/types/global";
@@ -5,11 +5,8 @@ import toast, { Toaster } from "react-hot-toast";
import {
faClose,
faCrown,
faFolder,
faUserPlus,
} from "@fortawesome/free-solid-svg-icons";
import { HexColorPicker } from "react-colorful";
import { Collection } from "@prisma/client";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { CollectionIncludingMembersAndLinkCount, Member } from "@/types/global";
import getPublicUserData from "@/lib/client/getPublicUserData";
-1
View File
@@ -110,7 +110,6 @@ export default function Navbar() {
<ProfilePhoto
src={account.image ? account.image : undefined}
priority={true}
className=""
/>
</div>
<ul className="dropdown-content z-[1] menu p-1 shadow bg-base-200 border border-neutral-content rounded-xl w-40 mt-1">
+12 -2
View File
@@ -8,6 +8,7 @@ type Props = {
className?: string;
priority?: boolean;
name?: string;
dimensionClass?: string;
};
export default function ProfilePhoto({
@@ -15,6 +16,7 @@ export default function ProfilePhoto({
className,
priority,
name,
dimensionClass,
}: Props) {
const [image, setImage] = useState("");
@@ -28,7 +30,11 @@ export default function ProfilePhoto({
}, [src]);
return !image ? (
<div className={`avatar w-8 h-8 placeholder ${className || ""}`}>
<div
className={`avatar placeholder ${className || ""} ${
dimensionClass || "w-8 h-8 "
}`}
>
<div className="bg-base-100 text-neutral rounded-full w-full h-full ring-2 ring-neutral-content">
{name ? (
<span className="text-2xl capitalize">{name.slice(0, 1)}</span>
@@ -41,7 +47,11 @@ export default function ProfilePhoto({
</div>
</div>
) : (
<div className={`avatar w-8 h-8 drop-shadow-md ${className || ""}`}>
<div
className={`avatar drop-shadow-md ${className || ""} ${
dimensionClass || "w-8 h-8 "
}`}
>
<div className="rounded-full w-full h-full ring-2 ring-neutral-content">
<Image
alt=""