Add database integration, auth API, admin/user portals, and deploy-db.sh
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
'use client';
|
||||
|
||||
import { useEffect, useRef, useState } from 'react';
|
||||
import { measureText } from '@chenglou/pretext';
|
||||
import { prepare, layout } from '@chenglou/pretext';
|
||||
|
||||
interface MeasuredTextProps {
|
||||
text: string;
|
||||
@@ -9,21 +9,17 @@ interface MeasuredTextProps {
|
||||
|
||||
export default function MeasuredText({ text }: MeasuredTextProps) {
|
||||
const ref = useRef<HTMLSpanElement>(null);
|
||||
const [width, setWidth] = useState<number | null>(null);
|
||||
const [height, setHeight] = useState<number | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (!ref.current) return;
|
||||
|
||||
const style = window.getComputedStyle(ref.current);
|
||||
const measured = measureText(text, {
|
||||
font: {
|
||||
family: style.fontFamily.split(',')[0].replace(/['"]/g, ''),
|
||||
size: parseFloat(style.fontSize),
|
||||
weight: style.fontWeight,
|
||||
},
|
||||
});
|
||||
const font = `${style.fontWeight} ${style.fontSize} ${style.fontFamily.split(',')[0].replace(/['"]/g, '')}`;
|
||||
const prepared = prepare(text, font);
|
||||
const { height } = layout(prepared, ref.current.offsetWidth, parseFloat(style.lineHeight) || parseFloat(style.fontSize) * 1.2);
|
||||
|
||||
setWidth(measured.width);
|
||||
setHeight(height);
|
||||
}, [text]);
|
||||
|
||||
return (
|
||||
@@ -31,8 +27,8 @@ export default function MeasuredText({ text }: MeasuredTextProps) {
|
||||
<span ref={ref} style={{ fontSize: '2rem', fontWeight: 700 }}>
|
||||
{text}
|
||||
</span>
|
||||
{width !== null && (
|
||||
<p style={{ color: 'dimgray' }}>Measured width: {width.toFixed(2)}px</p>
|
||||
{height !== null && (
|
||||
<p style={{ color: 'dimgray' }}>Measured height: {height.toFixed(2)}px</p>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import Link from 'next/link';
|
||||
import { useRouter } from 'next/navigation';
|
||||
import { useAuth } from '@/hooks/useAuth';
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
const links = [
|
||||
{ href: '/', label: 'Home' },
|
||||
@@ -13,11 +13,19 @@ const links = [
|
||||
];
|
||||
|
||||
export default function Navbar() {
|
||||
const { isLoggedIn, logout } = useAuth();
|
||||
const [auth, setAuth] = useState<{ authenticated: boolean; role?: string } | null>(null);
|
||||
const router = useRouter();
|
||||
|
||||
const handleLogout = () => {
|
||||
logout();
|
||||
useEffect(() => {
|
||||
fetch('/api/auth/me', { credentials: 'same-origin' })
|
||||
.then((res) => (res.ok ? res.json() : { authenticated: false }))
|
||||
.then((data) => setAuth(data))
|
||||
.catch(() => setAuth({ authenticated: false }));
|
||||
}, []);
|
||||
|
||||
const handleLogout = async () => {
|
||||
await fetch('/api/auth/logout', { method: 'POST', credentials: 'same-origin' });
|
||||
setAuth({ authenticated: false });
|
||||
router.push('/login');
|
||||
};
|
||||
|
||||
@@ -47,7 +55,7 @@ export default function Navbar() {
|
||||
{link.label}
|
||||
</Link>
|
||||
))}
|
||||
{isLoggedIn ? (
|
||||
{auth?.authenticated ? (
|
||||
<button
|
||||
onClick={handleLogout}
|
||||
style={{
|
||||
|
||||
Reference in New Issue
Block a user