feature: Set up post editing, modify add for proper sidebar.

This commit is contained in:
Keith Solomon
2025-07-22 10:05:57 -05:00
parent efe41d13d6
commit 20f0bf29bf
5 changed files with 181 additions and 4 deletions

View File

@@ -44,7 +44,11 @@ const formatDate = (dateStr: string | undefined) => {
<details name="prompt-details"> <details name="prompt-details">
<summary class="cursor-pointer font-semibold mt-2 text-lg">View Details</summary> <summary class="cursor-pointer font-semibold mt-2 text-lg">View Details</summary>
<div class="text-md border-t mt-2 pt-2"> <div class="text-md border-t mt-2 pt-2">
<h3 class="text-xl font-semibold px-2">Prompt</h3> <div class="flex justify-between items-center">
<h3 class="text-xl font-semibold px-2">Prompt</h3>
<a class="bg-green-600 text-white px-2 py-0 rounded text-sm hover:bg-green-700 transition-colors duration-300" href={`/edit?slug=${slug}`}>Edit</a>
</div>
<p class="my-2 px-2 text-balance">{description}</p> <p class="my-2 px-2 text-balance">{description}</p>
<hr class="my-2" /> <hr class="my-2" />
<p class="text-sm"><strong>Created:</strong> {formatDate(created_at)} &bull; <strong>Updated:</strong> {formatDate(updated_at)}</p> <p class="text-sm"><strong>Created:</strong> {formatDate(created_at)} &bull; <strong>Updated:</strong> {formatDate(updated_at)}</p>

View File

@@ -0,0 +1,17 @@
---
// Sidebar.astro
---
<aside class="w-64 border-r h-full p-4 text-gray-100">
<h2 class="text-lg font-semibold mb-4">Edit a prompt</h2>
<p class="text-sm">Use the form to edit an AI prompt in the catalog.</p>
<!-- <p class="text-sm mt-2">Make sure to include a title, type, description, and any relevant tags.</p> -->
<!-- <p class="text-sm mt-2">You can also add notes for your own reference.</p> -->
<a href="/" id="home" class="block w-fit bg-green-600 text-white px-4 py-2 mt-4 rounded hover:bg-green-700 transition-colors duration-300">
Go Back
</a>
</aside>

View File

@@ -1,6 +1,6 @@
--- ---
import "../styles/global.css"; import "../styles/global.css";
import Sidebar from "../components/Sidebar.astro"; import Sidebar from "../components/SidebarAdd.astro";
const supabaseUrl = import.meta.env.PUBLIC_SUPABASE_URL; const supabaseUrl = import.meta.env.PUBLIC_SUPABASE_URL;
const supabaseKey = import.meta.env.PUBLIC_SUPABASE_ANON_KEY; const supabaseKey = import.meta.env.PUBLIC_SUPABASE_ANON_KEY;
@@ -58,7 +58,7 @@ const supabaseKey = import.meta.env.PUBLIC_SUPABASE_ANON_KEY;
<div> <div>
<label for="description" class="block text-md font-semibold mb-1">Prompt</label> <label for="description" class="block text-md font-semibold mb-1">Prompt</label>
<textarea name="description" id="description" rows="4" required class="border p-2 w-full rounded"></textarea> <textarea name="description" id="description" rows="6" required class="border p-2 w-full rounded"></textarea>
</div> </div>
<div> <div>
@@ -66,7 +66,7 @@ const supabaseKey = import.meta.env.PUBLIC_SUPABASE_ANON_KEY;
<textarea name="notes" id="notes" rows="3" required class="border p-2 w-full rounded"></textarea> <textarea name="notes" id="notes" rows="3" required class="border p-2 w-full rounded"></textarea>
</div> </div>
<button type="submit" class="bg-blue-600 text-white px-4 py-2 rounded"> <button type="submit" class="bg-blue-600 text-white px-4 py-2 rounded hover:bg-blue-700 transition-colors duration-300 cursor-pointer">
Add Prompt Add Prompt
</button> </button>
</form> </form>

156
src/pages/edit.astro Normal file
View File

@@ -0,0 +1,156 @@
---
import "../styles/global.css";
import Sidebar from "../components/SidebarEdit.astro";
const supabaseUrl = import.meta.env.PUBLIC_SUPABASE_URL;
const supabaseKey = import.meta.env.PUBLIC_SUPABASE_ANON_KEY;
---
<html lang="en">
<head>
<title>Prompt Catalog - Edit Prompt</title>
</head>
<body class="font-sans antialiased bg-gray-800 text-gray-100">
<div
id="supabase-env"
data-url={supabaseUrl}
data-key={supabaseKey}
hidden
></div>
<div class="border-b p-4">
<h1 class="text-2xl font-bold">Prompt Catalog - Add New Prompt</h1>
<p class="text-sm mt-1">Add a new AI prompt to the catalog</p>
</div>
<div class="flex h-screen">
<Sidebar />
<div class="flex-1 flex flex-col overflow-hidden">
<main class="flex-1 overflow-y-auto p-4">
<div id="edit-root">Loading...</div>
</main>
</div>
</div>
<script type="module">
import { createClient } from 'https://cdn.jsdelivr.net/npm/@supabase/supabase-js/+esm';
const env = document.getElementById('supabase-env').dataset;
const supabase = createClient(env.url, env.key);
const slug = new URLSearchParams(window.location.search).get('slug');
const root = document.getElementById('edit-root');
if (!slug) {
root.innerHTML = `<p class="text-red-600 font-medium">❌ No slug provided.</p>`;
} else {
const { data, error } = await supabase
.from('prompts')
.select('*')
.eq('slug', slug)
.limit(1);
const prompt = data?.[0];
if (error || !prompt) {
root.innerHTML = `<p class="text-red-600 font-medium">❌ Prompt not found or error loading it.</p>`;
} else {
root.innerHTML = `
<form id="edit-form" class="space-y-4">
<input type="hidden" name="slug" value="${prompt.slug}" />
<div>
<label for="title" class="block text-md font-semibold mb-1">Title</label>
<input name="title" id="title" value="${prompt.title}" required class="border p-2 w-full rounded" />
</div>
<div class="grid grid-cols-1 sm:grid-cols-2 gap-4">
<div>
<label for="type" class="block text-md font-semibold mb-1">Type</label>
<select name="type" id="type" required class="border p-2 w-full rounded">
<option value="System" ${prompt.type === 'System' ? 'selected' : ''}>System</option>
<option value="Task" ${prompt.type === 'Task' ? 'selected' : ''}>Task</option>
</select>
</div>
<div>
<label for="tags" class="block text-md font-semibold mb-1">Tags (comma-separated)</label>
<input name="tags" id="tags" value="${(prompt.tags ?? []).join(', ')}" class="border p-2 pt-1 w-full rounded" />
</div>
</div>
<div>
<label for="description" class="block text-md font-semibold mb-1">Prompt</label>
<textarea name="description" id="description" rows="6" required class="border p-2 w-full rounded">${prompt.description}</textarea>
</div>
<div>
<label for="notes" class="block text-md font-semibold mb-1">Description</label>
<textarea name="notes" id="notes" rows="3" class="border p-2 w-full rounded">${prompt.notes ?? ''}</textarea>
</div>
<button type="submit" class="bg-blue-600 text-white px-4 py-2 rounded hover:bg-blue-700 transition-colors duration-300 cursor-pointer">
Save Changes
</button>
<div class="flex justify-between items-center pt-4 border-t mt-6">
<span class="text-lg text-red-400 font-bold">Be careful! Deletion is permanent.</span>
<button
id="delete-btn"
type="button"
class="bg-red-600 text-white px-4 py-2 rounded hover:bg-red-700 transition-colors duration-300 cursor-pointer"
>
Delete Prompt
</button>
</div>
</form>
<div id="success" class="text-green-600 mt-4 hidden">Prompt Updated.</div>
<div id="error" class="text-red-600 mt-4 hidden"></div>
`;
document.getElementById('edit-form').addEventListener('submit', async (e) => {
e.preventDefault();
const formData = new FormData(e.target);
const payload = {
title: formData.get('title'),
type: formData.get('type'),
description: formData.get('description'),
tags: formData.get('tags')?.split(',').map(t => t.trim()).filter(Boolean),
notes: formData.get('notes')
};
const { error: updateError } = await supabase
.from('prompts')
.update(payload)
.eq('slug', slug);
document.getElementById('success').style.display = updateError ? 'none' : 'block';
document.getElementById('error').innerText = updateError?.message || '';
document.getElementById('error').style.display = updateError ? 'block' : 'none';
});
document.getElementById('delete-btn').addEventListener('click', async () => {
const confirmed = window.confirm("Are you sure you want to delete this prompt? This cannot be undone.");
if (!confirmed) return;
const { error: deleteError } = await supabase
.from('prompts')
.delete()
.eq('slug', slug);
if (deleteError) {
document.getElementById('error').innerText = deleteError.message;
document.getElementById('error').style.display = 'block';
} else {
window.location.href = '/';
}
});
}
}
</script>
</body>
</html>