mirror of
https://github.com/willchen96/mike.git
synced 2026-07-12 22:42:11 +02:00
Add local repo contents
This commit is contained in:
parent
65739ef1ce
commit
d9690965b5
176 changed files with 68998 additions and 0 deletions
93
frontend/src/app/components/shared/OwnerOnlyModal.tsx
Normal file
93
frontend/src/app/components/shared/OwnerOnlyModal.tsx
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
"use client";
|
||||
|
||||
import { createPortal } from "react-dom";
|
||||
import { Lock, X } from "lucide-react";
|
||||
|
||||
interface Props {
|
||||
open: boolean;
|
||||
onClose: () => void;
|
||||
/** Short headline above the body, e.g. "Owner-only action". */
|
||||
title?: string;
|
||||
/** Sentence describing what the user tried to do. */
|
||||
action?: string;
|
||||
/** Email of the project/resource owner, shown so the user knows who to ask. */
|
||||
ownerEmail?: string | null;
|
||||
/** Override the default message entirely. */
|
||||
message?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lightweight "you don't have permission" modal shown when a non-owner
|
||||
* attempts an owner-only action (manage people, rename, delete, …) on a
|
||||
* shared project. Replaces the silent 404 the backend would otherwise
|
||||
* return so the user understands why the action didn't go through.
|
||||
*/
|
||||
export function OwnerOnlyModal({
|
||||
open,
|
||||
onClose,
|
||||
title = "Owner-only action",
|
||||
action,
|
||||
ownerEmail,
|
||||
message,
|
||||
}: Props) {
|
||||
if (!open) return null;
|
||||
|
||||
const body =
|
||||
message ??
|
||||
(action
|
||||
? `Only the project owner can ${action}.`
|
||||
: "Only the project owner can perform this action.");
|
||||
|
||||
return createPortal(
|
||||
<div
|
||||
className="fixed inset-0 z-[200] flex items-center justify-center bg-black/10 backdrop-blur-xs"
|
||||
onClick={onClose}
|
||||
>
|
||||
<div
|
||||
className="w-full max-w-md rounded-2xl bg-white shadow-2xl flex flex-col"
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
>
|
||||
{/* Header */}
|
||||
<div className="flex items-start justify-between gap-3 px-5 pt-5 pb-2">
|
||||
<div className="flex items-center gap-2">
|
||||
<Lock className="h-4 w-4 text-amber-600" />
|
||||
<h2 className="text-base font-medium text-gray-900">
|
||||
{title}
|
||||
</h2>
|
||||
</div>
|
||||
<button
|
||||
onClick={onClose}
|
||||
className="rounded-lg p-1.5 text-gray-400 hover:bg-gray-100 hover:text-gray-600"
|
||||
>
|
||||
<X className="h-4 w-4" />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* Body */}
|
||||
<div className="px-5 pb-2 pt-1">
|
||||
<p className="text-sm text-gray-600 leading-relaxed">
|
||||
{body}
|
||||
</p>
|
||||
{ownerEmail && (
|
||||
<p className="mt-2 text-xs text-gray-400">
|
||||
Ask{" "}
|
||||
<span className="text-gray-600">{ownerEmail}</span>{" "}
|
||||
if you need access.
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Footer */}
|
||||
<div className="flex justify-end gap-2 px-5 pb-5 pt-3">
|
||||
<button
|
||||
onClick={onClose}
|
||||
className="rounded-lg bg-gray-900 px-4 py-1.5 text-sm font-medium text-white hover:bg-gray-700"
|
||||
>
|
||||
OK
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>,
|
||||
document.body,
|
||||
);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue