yeas
This commit is contained in:
2
posts/pinned.json
Normal file
2
posts/pinned.json
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
[
|
||||||
|
]
|
||||||
@@ -61,6 +61,7 @@ export default function AdminPage() {
|
|||||||
}
|
}
|
||||||
return [];
|
return [];
|
||||||
});
|
});
|
||||||
|
const [pinFeedback, setPinFeedback] = useState<string | null>(null);
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -300,14 +301,45 @@ export default function AdminPage() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handlePin = (slug: string) => {
|
const handlePin = async (slug: string) => {
|
||||||
setPinned((prev) =>
|
setPinned((prev) => {
|
||||||
prev.includes(slug) ? prev.filter((s) => s !== slug) : [slug, ...prev]
|
const newPinned = prev.includes(slug)
|
||||||
);
|
? prev.filter((s) => s !== slug)
|
||||||
|
: [slug, ...prev];
|
||||||
|
// Update pinned.json on the server
|
||||||
|
fetch('/api/admin/posts', {
|
||||||
|
method: 'PATCH',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify({ pinned: newPinned }),
|
||||||
|
})
|
||||||
|
.then((res) => {
|
||||||
|
if (!res.ok) {
|
||||||
|
res.json().then((data) => {
|
||||||
|
setPinFeedback(data.error || 'Failed to update pinned posts');
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
setPinFeedback(
|
||||||
|
newPinned.includes(slug)
|
||||||
|
? 'Post pinned!'
|
||||||
|
: 'Post unpinned!'
|
||||||
|
);
|
||||||
|
setTimeout(() => setPinFeedback(null), 2000);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
setPinFeedback('Failed to update pinned posts');
|
||||||
|
});
|
||||||
|
return newPinned;
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-gray-100 p-8">
|
<div className="min-h-screen bg-gray-100 p-8">
|
||||||
|
{pinFeedback && (
|
||||||
|
<div className="fixed top-4 left-1/2 transform -translate-x-1/2 bg-blue-600 text-white px-6 py-2 rounded shadow-lg z-50">
|
||||||
|
{pinFeedback}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
{!isAuthenticated ? (
|
{!isAuthenticated ? (
|
||||||
<div className="max-w-md mx-auto bg-white p-8 rounded-lg shadow-md">
|
<div className="max-w-md mx-auto bg-white p-8 rounded-lg shadow-md">
|
||||||
<h1 className="text-2xl font-bold mb-6">Admin Login</h1>
|
<h1 className="text-2xl font-bold mb-6">Admin Login</h1>
|
||||||
@@ -598,10 +630,15 @@ export default function AdminPage() {
|
|||||||
key={post.slug}
|
key={post.slug}
|
||||||
className={`border rounded-lg p-3 flex items-center gap-3 justify-between ${pinned.includes(post.slug) ? 'bg-yellow-100 border-yellow-400' : ''}`}
|
className={`border rounded-lg p-3 flex items-center gap-3 justify-between ${pinned.includes(post.slug) ? 'bg-yellow-100 border-yellow-400' : ''}`}
|
||||||
>
|
>
|
||||||
<div className="flex-1 text-left">
|
<div className="flex-1 text-left flex items-center gap-2">
|
||||||
<div className="font-semibold">{post.title}</div>
|
{pinned.includes(post.slug) && (
|
||||||
<div className="text-xs text-gray-500">{post.date}</div>
|
<span title="Pinned" className="text-xl">📌</span>
|
||||||
<div className="text-xs text-gray-400">{post.summary}</div>
|
)}
|
||||||
|
<div>
|
||||||
|
<div className="font-semibold">{post.title}</div>
|
||||||
|
<div className="text-xs text-gray-500">{post.date}</div>
|
||||||
|
<div className="text-xs text-gray-400">{post.summary}</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<button
|
<button
|
||||||
onClick={() => handlePin(post.slug)}
|
onClick={() => handlePin(post.slug)}
|
||||||
|
|||||||
@@ -36,4 +36,23 @@ export async function POST(request: Request) {
|
|||||||
{ status: 500 }
|
{ status: 500 }
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function PATCH(request: Request) {
|
||||||
|
try {
|
||||||
|
const body = await request.json();
|
||||||
|
const { pinned } = body; // expects an array of slugs
|
||||||
|
if (!Array.isArray(pinned)) {
|
||||||
|
return NextResponse.json({ error: 'Invalid pinned data' }, { status: 400 });
|
||||||
|
}
|
||||||
|
const pinnedPath = path.join(postsDirectory, 'pinned.json');
|
||||||
|
fs.writeFileSync(pinnedPath, JSON.stringify(pinned, null, 2), 'utf8');
|
||||||
|
return NextResponse.json({ success: true });
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error updating pinned.json:', error);
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: 'Error updating pinned.json' },
|
||||||
|
{ status: 500 }
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user