Fix pnpm build

This commit is contained in:
UltraLionFr
2025-08-20 16:41:27 +02:00
parent 3de3e6f35a
commit 9730e21999
16 changed files with 134 additions and 83 deletions
+12 -14
View File
@@ -1,24 +1,23 @@
'use client';
import { useRouter } from 'next/navigation';
import Prism from 'prismjs';
import { use, useEffect, useState } from 'react';
import { use, useCallback, useEffect, useState } from 'react';
import 'prismjs/plugins/line-numbers/prism-line-numbers.css';
import 'prismjs/plugins/line-numbers/prism-line-numbers.js';
import 'prismjs/themes/prism-tomorrow.css';
import AuthSection from "@/components/paste-form/AuthSection";
import AuthSection from '@/components/paste-form/AuthSection';
import CodeViewer from '@/components/paste/CodeViewer';
import LoadingPaste from '@/components/paste/LoadingPaste';
import PasswordForm from '@/components/paste/PasswordForm';
import PasteSidebar from '@/components/paste/PasteSidebar';
import { Paste } from '@/types/paste';
async function loadLanguage(lang: string) {
try {
await import(`prismjs/components/prism-${lang}.js`);
} catch (err) {
} catch {
console.warn(`[Prism] Language '${lang}' introuvable. Fallback -> plaintext`);
}
}
@@ -29,14 +28,13 @@ export default function PastePage({
params: Promise<{ id: string }>;
}) {
const { id } = use(params);
const router = useRouter();
const [paste, setPaste] = useState<any | null>(null);
const [paste, setPaste] = useState<Paste | null>(null);
const [error, setError] = useState('');
const [loading, setLoading] = useState(true);
const [language, setLanguage] = useState<string>('language-javascript');
const fetchPaste = async (pwd?: string) => {
const fetchPaste = useCallback(async (pwd?: string) => {
setLoading(true);
const res = await fetch(`/api/paste/${id}`, {
method: 'POST',
@@ -55,7 +53,7 @@ export default function PastePage({
return;
}
const data = await res.json();
const data: Paste = await res.json();
setPaste(data);
const content = data.content.toLowerCase();
@@ -81,11 +79,11 @@ export default function PastePage({
setLanguage(`language-${detected}`);
setLoading(false);
};
}, [id]);
useEffect(() => {
fetchPaste();
}, [id]);
}, [fetchPaste]);
useEffect(() => {
if (paste?.content) Prism.highlightAll();
@@ -99,9 +97,9 @@ export default function PastePage({
return (
<div className="relative w-screen h-screen bg-[#0e0f13] text-white flex overflow-hidden">
<CodeViewer paste={paste} language={language} />
<PasteSidebar paste={paste} id={id} />
<CodeViewer paste={paste!} language={language} />
<PasteSidebar paste={paste!} id={id} />
<AuthSection />
</div>
);
}
}
+20 -7
View File
@@ -4,7 +4,13 @@ import { Player } from "@lordicon/react";
import { motion } from "framer-motion";
import { ArrowLeft } from "lucide-react";
import { useRouter } from "next/navigation";
import { forwardRef, useEffect, useRef, useState } from "react";
import {
ForwardedRef,
forwardRef,
useEffect,
useRef,
useState,
} from "react";
// URLs dicônes Lordicon
const icons = {
@@ -17,13 +23,20 @@ const icons = {
// Wrapper pour Lordicon
const LordIcon = forwardRef(function LordIcon(
{ url, size = 30, colorize = "#3b82f6" }: { url: string; size?: number; colorize?: string },
ref: any
{
url,
size = 30,
colorize = "#3b82f6",
}: { url: string; size?: number; colorize?: string },
ref: ForwardedRef<Player>
) {
const [iconData, setIconData] = useState<any>(null);
const [iconData, setIconData] = useState<Record<string, unknown> | null>(null);
useEffect(() => {
fetch(url).then((res) => res.json()).then(setIconData);
fetch(url)
.then((res) => res.json())
.then(setIconData)
.catch(() => setIconData(null));
}, [url]);
if (!iconData) return null;
@@ -40,7 +53,7 @@ function FeatureCard({
desc: string;
icon: string;
}) {
const iconRef = useRef<any>(null);
const iconRef = useRef<Player>(null);
return (
<motion.div
@@ -76,7 +89,7 @@ function ContactButton({
shadow: string;
color?: string;
}) {
const iconRef = useRef<any>(null);
const iconRef = useRef<Player>(null);
return (
<motion.a
-30
View File
@@ -1,30 +0,0 @@
import { prisma } from '@/lib/prisma';
interface Props {
params: { id: string };
}
export default async function PastePage({ params }: Props) {
const paste = await prisma.paste.findUnique({
where: { id: params.id },
select: { title: true, content: true, createdAt: true, views: true },
});
if (!paste) return <div>Paste not found</div>;
return (
<div className="min-h-screen bg-[#0e0f13] text-white p-6">
<h1 className="text-3xl font-bold text-blue-400 mb-4">
{paste.title || 'Untitled'}
</h1>
<pre className="bg-[#11131c] p-6 rounded-xl whitespace-pre-wrap overflow-auto text-sm border border-white/10 shadow-lg">
{paste.content}
</pre>
<p className="mt-4 text-xs text-neutral-400">
Views: {paste.views} · Created at: {new Date(paste.createdAt).toLocaleString()}
</p>
</div>
);
}
+46 -8
View File
@@ -30,13 +30,34 @@ const dashboardIcons = {
paste: "https://cdn.lordicon.com/hmpomorl.json",
};
// ---- Types ----
interface DashboardStats {
totalPastes: number;
totalViews: number;
recentPastes: number;
apiUsage: number;
storageUsed: number;
avgViews: number;
mostViewed: number;
avgSize: number;
}
interface Paste {
id: string;
title: string;
content: string;
createdAt: string;
views: number;
maxViews: number | null;
}
export default function DashboardPage() {
const { data: session, status } = useSession();
const router = useRouter();
const [searchTerm, setSearchTerm] = useState("");
const [stats, setStats] = useState<any>(null);
const [pastes, setPastes] = useState<any[]>([]);
const [stats, setStats] = useState<DashboardStats | null>(null);
const [pastes, setPastes] = useState<Paste[]>([]);
const [page, setPage] = useState(1);
const [totalPastes, setTotalPastes] = useState(0);
const [deleteId, setDeleteId] = useState<string | null>(null);
@@ -60,16 +81,22 @@ export default function DashboardPage() {
if (status === "authenticated") {
const fetchStats = async () => {
const res = await fetch("/api/stats");
if (res.ok) setStats(await res.json());
if (res.ok) {
const data: DashboardStats = await res.json();
setStats(data);
}
};
const fetchPastes = async () => {
const res = await fetch(
`/api/user-pastes?page=${page}&perPage=${PER_PAGE}&q=${encodeURIComponent(searchTerm)}`
);
if (!res.ok) return setPastes([]);
if (!res.ok) {
setPastes([]);
return;
}
try {
const data = await res.json();
const data: { pastes: Paste[]; total: number } = await res.json();
setPastes(data.pastes ?? []);
setTotalPastes(data.total ?? 0);
} catch {
@@ -92,7 +119,7 @@ export default function DashboardPage() {
<Sidebar />
<main className="flex-1 p-8 overflow-y-auto">
<Header user={session?.user?.name} />
<Header user={session?.user?.name ?? "User"} />
{/* Stats */}
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-6 mb-10">
@@ -110,7 +137,13 @@ export default function DashboardPage() {
))}
</div>
<SearchBar value={searchTerm} onChange={(v) => { setSearchTerm(v); setPage(1); }} />
<SearchBar
value={searchTerm}
onChange={(v) => {
setSearchTerm(v);
setPage(1);
}}
/>
{/* Pastes */}
<h2 className="text-lg font-semibold text-white mb-4">Your Pastes</h2>
@@ -134,7 +167,12 @@ export default function DashboardPage() {
<ConfirmDeleteModal
open={!!deleteId}
onOpenChange={(open) => !open && setDeleteId(null)}
onConfirm={() => { if (deleteId) { handleDelete(deleteId); setDeleteId(null); } }}
onConfirm={() => {
if (deleteId) {
handleDelete(deleteId);
setDeleteId(null);
}
}}
/>
</main>
</div>
+1 -1
View File
@@ -30,7 +30,7 @@ export default function NotFoundPage() {
</h2>
<p className="text-base text-neutral-400 mb-10 leading-relaxed">
The paste you're looking for might have been deleted, expired, or the
The paste you&apos;re looking for might have been deleted, expired, or the
URL is incorrect.
</p>