updated widgets

This commit is contained in:
2026-02-25 17:35:01 +09:00
parent 787724b09c
commit e4d2966377
43 changed files with 3648 additions and 180 deletions

View File

@@ -0,0 +1,17 @@
import { PageProps } from "@/app/(client)/[slug]/page";
import PostPage from "@/app/(client)/[slug]/page";
import ClientLayout from "@/app/(client)/layout";
import Post from "@/components/Post/Post";
import Tiptap from "@/components/Tiptap/Tiptap";
export default async function EditorPage({ params }: PageProps) {
const { slug } = await params;
const pageData = await fetch(`${process.env.NEXT_PUBLIC_API_URL}/api/pages/${slug}`, {
//next: { revalidate: 60 },
}).then(res => res.json());
return (
<Tiptap slug={slug} data={pageData} />
)
}

View File

@@ -0,0 +1,91 @@
'use client'
import { WebVitalsCard } from "@/components/WebVitalsCard"
import { useWebVitals } from "@/hooks/useWebVitals"
const AdminPage = () => {
const metrics = useWebVitals()
const vitalsConfig = [
{
title: 'Time to First Byte (TTFB)',
value: metrics.TTFB,
unit: 'ms',
description: 'Time between request and first byte of response',
thresholds: { good: 200, needsImprovement: 500 }
},
{
title: 'First Contentful Paint (FCP)',
value: metrics.FCP,
unit: 'ms',
description: 'Time until first content is rendered',
thresholds: { good: 1800, needsImprovement: 3000 }
},
{
title: 'Largest Contentful Paint (LCP)',
value: metrics.LCP,
unit: 'ms',
description: 'Time until largest content element is rendered',
thresholds: { good: 2500, needsImprovement: 4000 }
},
{
title: 'First Input Delay (FID)',
value: metrics.FID,
unit: 'ms',
description: 'Time from first user interaction to browser response',
thresholds: { good: 100, needsImprovement: 300 }
},
{
title: 'Cumulative Layout Shift (CLS)',
value: metrics.CLS,
unit: '',
description: 'Measures visual stability (lower is better)',
thresholds: { good: 0.1, needsImprovement: 0.25 }
},
{
title: 'Interaction to Next Paint (INP)',
value: metrics.INP,
unit: 'ms',
description: 'Measures responsiveness to user interactions',
thresholds: { good: 200, needsImprovement: 500 }
}
]
return (
<div className="min-h-screen bg-gray-50 py-8">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div className="mb-8">
<h1 className="text-3xl font-bold text-gray-900">Web Vitals Dashboard</h1>
<p className="mt-2 text-gray-600">
Real-time Core Web Vitals metrics for your Next.js application
</p>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
{vitalsConfig.map((vital) => (
<WebVitalsCard
key={vital.title}
title={vital.title}
value={vital.value}
unit={vital.unit}
description={vital.description}
thresholds={vital.thresholds}
/>
))}
</div>
<div className="mt-8 p-4 bg-blue-50 border border-blue-200 rounded-lg">
<h2 className="text-lg font-semibold text-blue-900 mb-2">About Core Web Vitals</h2>
<p className="text-sm text-blue-800">
Core Web Vitals are a set of real-world, user-centered metrics that quantify key aspects
of user experience. They measure dimensions of web usability such as load time,
interactivity, and the stability of content as it loads.
</p>
</div>
</div>
</div>
)
}
export default AdminPage

View File

@@ -0,0 +1,354 @@
import React from 'react'
const PostsPage = () => {
return (
<div className='p-4'>
<div className="">
<table className="table table-pin-rows table-pin-cols">
{/* head */}
<thead>
<tr>
<th>
<label>
<input type="checkbox" className="checkbox" />
</label>
</th>
<th>Name</th>
<th>Job</th>
<th>Favorite Color</th>
<th></th>
</tr>
</thead>
<tbody>
{/* row 1 */}
<tr>
<th>
<label>
<input type="checkbox" className="checkbox" />
</label>
</th>
<td>
<div className="flex items-center gap-3">
<div className="avatar">
<div className="mask mask-squircle h-12 w-12">
<img
src="https://img.daisyui.com/images/profile/demo/2@94.webp"
alt="Avatar Tailwind CSS Component" />
</div>
</div>
<div>
<div className="font-bold">Hart Hagerty</div>
<div className="text-sm opacity-50">United States</div>
</div>
</div>
</td>
<td>
Zemlak, Daniel and Leannon
<br />
<span className="badge badge-ghost badge-sm">Desktop Support Technician</span>
</td>
<td>Purple</td>
<th>
<button className="btn btn-ghost btn-xs">details</button>
</th>
</tr>
{/* row 2 */}
<tr>
<th>
<label>
<input type="checkbox" className="checkbox" />
</label>
</th>
<td>
<div className="flex items-center gap-3">
<div className="avatar">
<div className="mask mask-squircle h-12 w-12">
<img
src="https://img.daisyui.com/images/profile/demo/3@94.webp"
alt="Avatar Tailwind CSS Component" />
</div>
</div>
<div>
<div className="font-bold">Brice Swyre</div>
<div className="text-sm opacity-50">China</div>
</div>
</div>
</td>
<td>
Carroll Group
<br />
<span className="badge badge-ghost badge-sm">Tax Accountant</span>
</td>
<td>Red</td>
<th>
<button className="btn btn-ghost btn-xs">details</button>
</th>
</tr>
{/* row 3 */}
<tr>
<th>
<label>
<input type="checkbox" className="checkbox" />
</label>
</th>
<td>
<div className="flex items-center gap-3">
<div className="avatar">
<div className="mask mask-squircle h-12 w-12">
<img
src="https://img.daisyui.com/images/profile/demo/4@94.webp"
alt="Avatar Tailwind CSS Component" />
</div>
</div>
<div>
<div className="font-bold">Marjy Ferencz</div>
<div className="text-sm opacity-50">Russia</div>
</div>
</div>
</td>
<td>
Rowe-Schoen
<br />
<span className="badge badge-ghost badge-sm">Office Assistant I</span>
</td>
<td>Crimson</td>
<th>
<button className="btn btn-ghost btn-xs">details</button>
</th>
</tr>
{/* row 4 */}
<tr>
<th>
<label>
<input type="checkbox" className="checkbox" />
</label>
</th>
<td>
<div className="flex items-center gap-3">
<div className="avatar">
<div className="mask mask-squircle h-12 w-12">
<img
src="https://img.daisyui.com/images/profile/demo/5@94.webp"
alt="Avatar Tailwind CSS Component" />
</div>
</div>
<div>
<div className="font-bold">Yancy Tear</div>
<div className="text-sm opacity-50">Brazil</div>
</div>
</div>
</td>
<td>
Wyman-Ledner
<br />
<span className="badge badge-ghost badge-sm">Community Outreach Specialist</span>
</td>
<td>Indigo</td>
<th>
<button className="btn btn-ghost btn-xs">details</button>
</th>
</tr>
<tr>
<th>
<label>
<input type="checkbox" className="checkbox" />
</label>
</th>
<td>
<div className="flex items-center gap-3">
<div className="avatar">
<div className="mask mask-squircle h-12 w-12">
<img
src="https://img.daisyui.com/images/profile/demo/5@94.webp"
alt="Avatar Tailwind CSS Component" />
</div>
</div>
<div>
<div className="font-bold">Yancy Tear</div>
<div className="text-sm opacity-50">Brazil</div>
</div>
</div>
</td>
<td>
Wyman-Ledner
<br />
<span className="badge badge-ghost badge-sm">Community Outreach Specialist</span>
</td>
<td>Indigo</td>
<th>
<button className="btn btn-ghost btn-xs">details</button>
</th>
</tr>
<tr>
<th>
<label>
<input type="checkbox" className="checkbox" />
</label>
</th>
<td>
<div className="flex items-center gap-3">
<div className="avatar">
<div className="mask mask-squircle h-12 w-12">
<img
src="https://img.daisyui.com/images/profile/demo/5@94.webp"
alt="Avatar Tailwind CSS Component" />
</div>
</div>
<div>
<div className="font-bold">Yancy Tear</div>
<div className="text-sm opacity-50">Brazil</div>
</div>
</div>
</td>
<td>
Wyman-Ledner
<br />
<span className="badge badge-ghost badge-sm">Community Outreach Specialist</span>
</td>
<td>Indigo</td>
<th>
<button className="btn btn-ghost btn-xs">details</button>
</th>
</tr>
<tr>
<th>
<label>
<input type="checkbox" className="checkbox" />
</label>
</th>
<td>
<div className="flex items-center gap-3">
<div className="avatar">
<div className="mask mask-squircle h-12 w-12">
<img
src="https://img.daisyui.com/images/profile/demo/5@94.webp"
alt="Avatar Tailwind CSS Component" />
</div>
</div>
<div>
<div className="font-bold">Yancy Tear</div>
<div className="text-sm opacity-50">Brazil</div>
</div>
</div>
</td>
<td>
Wyman-Ledner
<br />
<span className="badge badge-ghost badge-sm">Community Outreach Specialist</span>
</td>
<td>Indigo</td>
<th>
<button className="btn btn-ghost btn-xs">details</button>
</th>
</tr>
<tr>
<th>
<label>
<input type="checkbox" className="checkbox" />
</label>
</th>
<td>
<div className="flex items-center gap-3">
<div className="avatar">
<div className="mask mask-squircle h-12 w-12">
<img
src="https://img.daisyui.com/images/profile/demo/5@94.webp"
alt="Avatar Tailwind CSS Component" />
</div>
</div>
<div>
<div className="font-bold">Yancy Tear</div>
<div className="text-sm opacity-50">Brazil</div>
</div>
</div>
</td>
<td>
Wyman-Ledner
<br />
<span className="badge badge-ghost badge-sm">Community Outreach Specialist</span>
</td>
<td>Indigo</td>
<th>
<button className="btn btn-ghost btn-xs">details</button>
</th>
</tr>
<tr>
<th>
<label>
<input type="checkbox" className="checkbox" />
</label>
</th>
<td>
<div className="flex items-center gap-3">
<div className="avatar">
<div className="mask mask-squircle h-12 w-12">
<img
src="https://img.daisyui.com/images/profile/demo/5@94.webp"
alt="Avatar Tailwind CSS Component" />
</div>
</div>
<div>
<div className="font-bold">Yancy Tear</div>
<div className="text-sm opacity-50">Brazil</div>
</div>
</div>
</td>
<td>
Wyman-Ledner
<br />
<span className="badge badge-ghost badge-sm">Community Outreach Specialist</span>
</td>
<td>Indigo</td>
<th>
<button className="btn btn-ghost btn-xs">details</button>
</th>
</tr>
<tr>
<th>
<label>
<input type="checkbox" className="checkbox" />
</label>
</th>
<td>
<div className="flex items-center gap-3">
<div className="avatar">
<div className="mask mask-squircle h-12 w-12">
<img
src="https://img.daisyui.com/images/profile/demo/5@94.webp"
alt="Avatar Tailwind CSS Component" />
</div>
</div>
<div>
<div className="font-bold">Yancy Tear</div>
<div className="text-sm opacity-50">Brazil</div>
</div>
</div>
</td>
<td>
Wyman-Ledner
<br />
<span className="badge badge-ghost badge-sm">Community Outreach Specialist</span>
</td>
<td>Indigo</td>
<th>
<button className="btn btn-ghost btn-xs">details</button>
</th>
</tr>
</tbody>
{/* foot */}
<tfoot>
<tr>
<th></th>
<th>Name</th>
<th>Job</th>
<th>Favorite Color</th>
<th></th>
</tr>
</tfoot>
</table>
</div>
</div>
)
}
export default PostsPage

View File

@@ -0,0 +1,70 @@
import { IconBook2, IconHome, IconSettings } from "@tabler/icons-react";
export default function EditLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<div className="drawer lg:drawer-open">
<input id="my-drawer-4" type="checkbox" className="drawer-toggle" />
<div className="drawer-content h-screen grid grid-rows-[min-content_1fr]">
{/* Navbar */}
<nav className="navbar w-full bg-base-300">
<label htmlFor="my-drawer-4" aria-label="open sidebar" className="btn btn-square btn-ghost">
{/* Sidebar toggle icon */}
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" strokeLinejoin="round" strokeLinecap="round" strokeWidth="2" fill="none" stroke="currentColor" className="my-1.5 inline-block size-4"><path d="M4 4m0 2a2 2 0 0 1 2 -2h12a2 2 0 0 1 2 2v12a2 2 0 0 1 -2 2h-12a2 2 0 0 1 -2 -2z"></path><path d="M9 4v16"></path><path d="M14 10l2 2l-2 2"></path></svg>
</label>
<div id="editor-navbar-title" className="px-4">
{/* Editor Navbar title goes here */}
</div>
<div id="editor-navbar" className="ml-auto flex space-x-2">
{/* Editor Navbar items go here */}
</div>
</nav>
{/* Page content here */}
<div className="overflow-auto max-h-full">
{children}
</div>
</div>
<div className="drawer-side is-drawer-close:overflow-visible">
<label htmlFor="my-drawer-4" aria-label="close sidebar" className="drawer-overlay"></label>
<div className="flex min-h-full flex-col items-start bg-base-200 is-drawer-close:w-14 is-drawer-open:w-64">
{/* Sidebar content here */}
<ul className="menu w-full grow border-r border-r-gray-300">
{/* List item */}
<li>
<a
role="button"
href="/admin"
className="is-drawer-close:tooltip is-drawer-close:tooltip-right" data-tip="Главная">
{/* Home icon */}
<IconHome className="my-1.5 inline-block size-4" size={16} />
<span className="is-drawer-close:hidden">Главная</span>
</a>
</li>
<li>
<a
role="button"
href="/admin/posts"
className="is-drawer-close:tooltip is-drawer-close:tooltip-right" data-tip="Записи">
<IconBook2 className="my-1.5 inline-block size-4" size={16} />
<span className="is-drawer-close:hidden">Записи</span>
</a>
</li>
{/* List item */}
<li>
<button className="is-drawer-close:tooltip is-drawer-close:tooltip-right" data-tip="Настройки">
<IconSettings className="my-1.5 inline-block size-4" size={16} />
<span className="is-drawer-close:hidden">Настройки</span>
</button>
</li>
</ul>
</div>
</div>
</div>
)
}