more more more
This commit is contained in:
@@ -1,7 +1,8 @@
|
|||||||
import { createSignal, Show } from "solid-js";
|
import { createSignal, Show } from "solid-js";
|
||||||
import type { CommentDeletionPromptProps, DeletionType } from "~/types/comment";
|
import type { CommentDeletionPromptProps, DeletionType } from "~/types/comment";
|
||||||
import UserDefaultImage from "~/components/icons/UserDefaultImage";
|
import UserDefaultImage from "~/components/icons/UserDefaultImage";
|
||||||
import Xmark from "~/components/icons/Xmark";
|
import Modal from "~/components/ui/Modal";
|
||||||
|
import Button from "~/components/ui/Button";
|
||||||
|
|
||||||
export default function CommentDeletionPrompt(
|
export default function CommentDeletionPrompt(
|
||||||
props: CommentDeletionPromptProps
|
props: CommentDeletionPromptProps
|
||||||
@@ -44,18 +45,12 @@ export default function CommentDeletionPrompt(
|
|||||||
normalDeleteChecked() || adminDeleteChecked() || fullDeleteChecked();
|
normalDeleteChecked() || adminDeleteChecked() || fullDeleteChecked();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div class="flex justify-center">
|
<Modal
|
||||||
<div class="fixed top-48 z-100 h-fit">
|
open={props.isOpen}
|
||||||
<div
|
onClose={props.onClose}
|
||||||
id="delete_prompt"
|
title="Comment Deletion"
|
||||||
class="fade-in bg-red rounded-md px-8 py-4 shadow-lg brightness-110"
|
class="bg-red brightness-110"
|
||||||
>
|
>
|
||||||
<button class="fixed right-4" onClick={() => props.onClose()}>
|
|
||||||
<Xmark strokeWidth={0.5} color="white" height={50} width={50} />
|
|
||||||
</button>
|
|
||||||
<div class="py-4 text-center text-3xl tracking-wide">
|
|
||||||
Comment Deletion
|
|
||||||
</div>
|
|
||||||
<div class="bg-surface0 mx-auto w-3/4 rounded px-6 py-4">
|
<div class="bg-surface0 mx-auto w-3/4 rounded px-6 py-4">
|
||||||
<div class="flex overflow-x-auto overflow-y-hidden select-text">
|
<div class="flex overflow-x-auto overflow-y-hidden select-text">
|
||||||
{/* Comment body will be passed as prop */}
|
{/* Comment body will be passed as prop */}
|
||||||
@@ -76,9 +71,7 @@ export default function CommentDeletionPrompt(
|
|||||||
/>
|
/>
|
||||||
</Show>
|
</Show>
|
||||||
<div class="px-1">
|
<div class="px-1">
|
||||||
{props.commenterDisplayName ||
|
{props.commenterDisplayName || props.commenterEmail || "[removed]"}
|
||||||
props.commenterEmail ||
|
|
||||||
"[removed]"}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -126,21 +119,16 @@ export default function CommentDeletionPrompt(
|
|||||||
</div>
|
</div>
|
||||||
</Show>
|
</Show>
|
||||||
<div class="flex w-full justify-center pt-2">
|
<div class="flex w-full justify-center pt-2">
|
||||||
<button
|
<Button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={deletionWrapper}
|
onClick={deletionWrapper}
|
||||||
disabled={props.commentDeletionLoading || !isDeleteEnabled()}
|
loading={props.commentDeletionLoading}
|
||||||
class={`${
|
disabled={!isDeleteEnabled()}
|
||||||
props.commentDeletionLoading || !isDeleteEnabled()
|
variant="danger"
|
||||||
? "bg-surface2 opacity-50"
|
|
||||||
: "border-red bg-red hover:brightness-125"
|
|
||||||
} rounded border px-4 py-2 text-base shadow-md transition-all duration-300 ease-in-out active:scale-90`}
|
|
||||||
>
|
>
|
||||||
Delete
|
Delete
|
||||||
</button>
|
</Button>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
</Modal>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -634,9 +634,8 @@ export default function CommentSectionWrapper(
|
|||||||
commentReaction={commentReaction}
|
commentReaction={commentReaction}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Show when={showingDeletionPrompt()}>
|
|
||||||
<div ref={deletePromptRef}>
|
|
||||||
<CommentDeletionPrompt
|
<CommentDeletionPrompt
|
||||||
|
isOpen={showingDeletionPrompt()}
|
||||||
commentID={commentIDForModification()}
|
commentID={commentIDForModification()}
|
||||||
commenterID={commenterForModification()}
|
commenterID={commenterForModification()}
|
||||||
commenterImage={commenterImageForModification()}
|
commenterImage={commenterImageForModification()}
|
||||||
@@ -650,12 +649,9 @@ export default function CommentSectionWrapper(
|
|||||||
clearModificationPrompt();
|
clearModificationPrompt();
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
|
||||||
</Show>
|
|
||||||
|
|
||||||
<Show when={showingCommentEdit()}>
|
|
||||||
<div ref={modificationPromptRef}>
|
|
||||||
<EditCommentModal
|
<EditCommentModal
|
||||||
|
isOpen={showingCommentEdit()}
|
||||||
commentID={commentIDForModification()}
|
commentID={commentIDForModification()}
|
||||||
commentBody={commentBodyForModification()}
|
commentBody={commentBodyForModification()}
|
||||||
commenterImage={commenterImageForModification()}
|
commenterImage={commenterImageForModification()}
|
||||||
@@ -668,8 +664,6 @@ export default function CommentSectionWrapper(
|
|||||||
clearModificationPrompt();
|
clearModificationPrompt();
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
|
||||||
</Show>
|
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { createSignal, Show } from "solid-js";
|
import { createSignal, Show } from "solid-js";
|
||||||
import type { EditCommentModalProps } from "~/types/comment";
|
import type { EditCommentModalProps } from "~/types/comment";
|
||||||
import Xmark from "~/components/icons/Xmark";
|
import Modal from "~/components/ui/Modal";
|
||||||
import Button from "~/components/ui/Button";
|
import Button from "~/components/ui/Button";
|
||||||
|
|
||||||
export default function EditCommentModal(props: EditCommentModalProps) {
|
export default function EditCommentModal(props: EditCommentModalProps) {
|
||||||
@@ -22,23 +22,12 @@ export default function EditCommentModal(props: EditCommentModalProps) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div class="z-100 flex justify-center">
|
<Modal
|
||||||
<div class="fixed top-48 h-fit w-11/12 sm:w-4/5 md:w-2/3">
|
open={props.isOpen}
|
||||||
<div
|
onClose={props.onClose}
|
||||||
id="edit_prompt"
|
title="Edit Comment"
|
||||||
class="fade-in bg-surface1 z-50 rounded-md px-8 py-4 shadow-lg"
|
class="bg-surface1 w-11/12 max-w-none sm:w-4/5 md:w-2/3"
|
||||||
>
|
>
|
||||||
<button class="absolute right-4" onClick={() => props.onClose()}>
|
|
||||||
<Xmark
|
|
||||||
strokeWidth={0.5}
|
|
||||||
color="var(--color-text)"
|
|
||||||
height={50}
|
|
||||||
width={50}
|
|
||||||
/>
|
|
||||||
</button>
|
|
||||||
<div class="text-text py-4 text-center text-3xl tracking-wide">
|
|
||||||
Edit Comment
|
|
||||||
</div>
|
|
||||||
<form onSubmit={editCommentWrapper}>
|
<form onSubmit={editCommentWrapper}>
|
||||||
<div class="textarea-group home">
|
<div class="textarea-group home">
|
||||||
<textarea
|
<textarea
|
||||||
@@ -65,8 +54,6 @@ export default function EditCommentModal(props: EditCommentModalProps) {
|
|||||||
<Show when={showNoChange()}>
|
<Show when={showNoChange()}>
|
||||||
<div class="text-red text-center italic">No change detected</div>
|
<div class="text-red text-center italic">No change detected</div>
|
||||||
</Show>
|
</Show>
|
||||||
</div>
|
</Modal>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
87
src/components/ui/Modal.tsx
Normal file
87
src/components/ui/Modal.tsx
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
import { Show, onMount, onCleanup, type JSX } from "solid-js";
|
||||||
|
import { Portal } from "solid-js/web";
|
||||||
|
import Xmark from "~/components/icons/Xmark";
|
||||||
|
|
||||||
|
export interface ModalProps {
|
||||||
|
/** Controls modal visibility */
|
||||||
|
open: boolean;
|
||||||
|
/** Callback when modal should close */
|
||||||
|
onClose: () => void;
|
||||||
|
/** Modal title (optional) */
|
||||||
|
title?: string | JSX.Element;
|
||||||
|
/** Modal content */
|
||||||
|
children: JSX.Element;
|
||||||
|
/** Action buttons (optional) */
|
||||||
|
actions?: JSX.Element;
|
||||||
|
/** Additional CSS classes for modal container */
|
||||||
|
class?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function Modal(props: ModalProps) {
|
||||||
|
const handleBackdropClick = (e: MouseEvent) => {
|
||||||
|
if (e.target === e.currentTarget) {
|
||||||
|
props.onClose();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleEscapeKey = (e: KeyboardEvent) => {
|
||||||
|
if (e.key === "Escape") {
|
||||||
|
props.onClose();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
onMount(() => {
|
||||||
|
if (props.open) {
|
||||||
|
document.addEventListener("keydown", handleEscapeKey);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
onCleanup(() => {
|
||||||
|
document.removeEventListener("keydown", handleEscapeKey);
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Show when={props.open}>
|
||||||
|
<Portal>
|
||||||
|
<div
|
||||||
|
class="fixed inset-0 z-50 flex items-center justify-center bg-black/50"
|
||||||
|
onClick={handleBackdropClick}
|
||||||
|
role="dialog"
|
||||||
|
aria-modal="true"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class={`bg-base fade-in relative mx-4 max-w-md rounded-md px-8 py-4 shadow-lg ${props.class || ""}`}
|
||||||
|
onClick={(e) => e.stopPropagation()}
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
class="absolute top-4 right-4"
|
||||||
|
onClick={props.onClose}
|
||||||
|
aria-label="Close modal"
|
||||||
|
>
|
||||||
|
<Xmark
|
||||||
|
strokeWidth={0.5}
|
||||||
|
color="var(--color-text)"
|
||||||
|
height={50}
|
||||||
|
width={50}
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<Show when={props.title}>
|
||||||
|
<div class="py-4 text-center text-3xl tracking-wide">
|
||||||
|
{props.title}
|
||||||
|
</div>
|
||||||
|
</Show>
|
||||||
|
|
||||||
|
<div class="modal-content">{props.children}</div>
|
||||||
|
|
||||||
|
<Show when={props.actions}>
|
||||||
|
<div class="modal-actions">{props.actions}</div>
|
||||||
|
</Show>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Portal>
|
||||||
|
</Show>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export { Modal };
|
||||||
@@ -176,6 +176,7 @@ export interface ReactionBarProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface CommentDeletionPromptProps {
|
export interface CommentDeletionPromptProps {
|
||||||
|
isOpen: boolean;
|
||||||
privilegeLevel: PrivilegeLevel;
|
privilegeLevel: PrivilegeLevel;
|
||||||
commentID: number;
|
commentID: number;
|
||||||
commenterID: string;
|
commenterID: string;
|
||||||
@@ -192,6 +193,7 @@ export interface CommentDeletionPromptProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface EditCommentModalProps {
|
export interface EditCommentModalProps {
|
||||||
|
isOpen: boolean;
|
||||||
commentID: number;
|
commentID: number;
|
||||||
commentBody: string;
|
commentBody: string;
|
||||||
editComment: (body: string, comment_id: number) => Promise<void>;
|
editComment: (body: string, comment_id: number) => Promise<void>;
|
||||||
|
|||||||
Reference in New Issue
Block a user