Add local repo contents

This commit is contained in:
willchen96 2026-04-29 19:49:06 +02:00
parent 65739ef1ce
commit d9690965b5
176 changed files with 68998 additions and 0 deletions

View file

@ -0,0 +1,81 @@
import { X } from "lucide-react";
import { createPortal } from "react-dom";
interface CreditsExhaustedModalProps {
isOpen: boolean;
onClose: () => void;
resetDate: string;
}
export function CreditsExhaustedModal({
isOpen,
onClose,
resetDate,
}: CreditsExhaustedModalProps) {
if (!isOpen) return null;
// Format the reset date
const formatResetDate = (dateString: string) => {
const date = new Date(dateString);
return date.toLocaleDateString("en-US", {
month: "long",
day: "numeric",
year: "numeric",
});
};
return createPortal(
<>
{/* Backdrop */}
<div
className="fixed inset-0 bg-black/50 z-[200]"
onClick={onClose}
/>
{/* Modal */}
<div className="fixed left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 z-[201] w-full max-w-md px-4">
<div className="relative bg-white rounded-2xl shadow-2xl p-6">
{/* Header */}
<div className="flex items-start justify-between mb-4">
<h2 className="text-3xl font-light font-eb-garamond text-gray-900">
Message Limit Reached
</h2>
</div>
{/* Content */}
<div className="space-y-4">
<p className="text-gray-600">
You've reached your monthly message limit of 100
messages.
</p>
<div className="bg-blue-50 border border-blue-200 rounded-lg p-4">
<p className="text-sm text-blue-900 font-medium mb-1">
Your credits will reset on:
</p>
<p className="text-lg font-semibold text-blue-700">
{formatResetDate(resetDate)}
</p>
</div>
<p className="text-sm text-gray-500">
Your message credits automatically reset on the
first day of each month.
</p>
</div>
{/* Actions */}
<div className="mt-6 flex gap-3">
<button
onClick={onClose}
className="flex-1 px-4 py-2.5 bg-gray-100 hover:bg-gray-200 text-gray-700 rounded-lg font-medium transition-colors"
>
Close
</button>
</div>
</div>
</div>
</>,
document.body,
);
}

View file

@ -0,0 +1,97 @@
"use client";
import { Button } from "@/components/ui/button";
import { X, Check } from "lucide-react";
interface DeleteChatsModalProps {
isOpen: boolean;
onClose: () => void;
onConfirm: () => void;
chatCount: number;
isDeleting: boolean;
isSuccess?: boolean;
}
export function DeleteChatsModal({
isOpen,
onClose,
onConfirm,
chatCount,
isDeleting,
isSuccess = false,
}: DeleteChatsModalProps) {
if (!isOpen) return null;
return (
<>
{/* Backdrop */}
<div
className="fixed inset-0 bg-black/50 z-199"
onClick={isDeleting || isSuccess ? undefined : onClose}
/>
{/* Modal */}
<div className="fixed left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 z-200 w-full max-w-md">
<div className="bg-white rounded-2xl shadow-2xl p-8">
{isSuccess ? (
<>
{/* Success State */}
<div className="text-center">
<div className="mx-auto w-16 h-16 bg-green-100 rounded-full flex items-center justify-center mb-4">
<Check className="h-8 w-8 text-green-600" />
</div>
<h2 className="text-3xl font-light font-eb-garamond text-gray-900 mb-2">
All Chats Deleted
</h2>
<p className="text-gray-600 text-sm">
Your chat history has been successfully
deleted.
</p>
</div>
</>
) : (
<>
{/* Header */}
<div className="flex items-center justify-between mb-6">
<h2 className="text-4xl font-light font-eb-garamond text-red-700">
Delete All Chats
</h2>
</div>
{/* Content */}
<div className="space-y-4">
<p className="text-gray-600 text-sm leading-relaxed">
Are you sure you want to delete all{" "}
{chatCount} chat
{chatCount !== 1 ? "s" : ""}? This action is
permanent and cannot be undone.
</p>
<div className="space-y-3 pt-4">
<Button
onClick={onConfirm}
disabled={isDeleting}
variant="destructive"
className="w-full bg-red-600 hover:bg-red-700 text-white"
>
{isDeleting
? "Deleting..."
: "Delete All Chats"}
</Button>
<Button
onClick={onClose}
variant="outline"
disabled={isDeleting}
className="w-full border-gray-300 text-gray-700 hover:bg-gray-50"
>
Cancel
</Button>
</div>
</div>
</>
)}
</div>
</div>
</>
);
}

View file

@ -0,0 +1,90 @@
import { X, Link2, Check } from "lucide-react";
import { useState } from "react";
import { createPortal } from "react-dom";
interface SimpleLinkDialogProps {
isOpen: boolean;
onClose: () => void;
shareUrl: string | null;
}
export function SimpleLinkDialog({
isOpen,
onClose,
shareUrl,
}: SimpleLinkDialogProps) {
const [linkCopied, setLinkCopied] = useState(false);
if (!isOpen) return null;
const handleCopyLink = async () => {
if (!shareUrl) return;
try {
await navigator.clipboard.writeText(shareUrl);
setLinkCopied(true);
setTimeout(() => setLinkCopied(false), 2000);
} catch (err) {}
};
return createPortal(
<>
{/* Backdrop */}
<div
className="fixed inset-0 bg-black/50 z-[199]"
onClick={onClose}
/>
{/* Dialog */}
<div className="fixed left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 z-[200] w-full max-w-md px-4">
<div className="relative bg-white rounded-2xl shadow-2xl p-6">
{/* Close Button */}
<button
onClick={onClose}
className="absolute right-4 top-4 text-gray-400 hover:text-gray-600 transition-colors"
>
<X className="h-5 w-5" />
</button>
{/* Header */}
<div className="flex items-center justify-between mb-6">
<h2 className="text-3xl font-light font-eb-garamond text-gray-900">
Share Chat
</h2>
</div>
{/* Content */}
<div className="space-y-4">
{/* Link display */}
<div className="bg-gray-50 rounded-lg p-3 border border-gray-200">
<p className="text-sm text-gray-600 mb-2 font-medium">
Share Link
</p>
<p className="text-sm text-gray-800 break-all font-mono">
{shareUrl}
</p>
</div>
{/* Copy button */}
<button
onClick={handleCopyLink}
className="w-full flex items-center justify-center gap-2 bg-blue-600 hover:bg-blue-700 text-white py-2.5 px-4 rounded-lg transition-colors font-medium"
>
{linkCopied ? (
<>
<Check className="h-5 w-5" />
Copied!
</>
) : (
<>
<Link2 className="h-5 w-5" />
Copy Link
</>
)}
</button>
</div>
</div>
</div>
</>,
document.body,
);
}