Create secrets

This commit is contained in:
2025-05-28 15:57:45 -07:00
parent 65ac4852df
commit 1ec4d0ac35

View File

@@ -1,21 +1,22 @@
import { createFileRoute } from '@tanstack/react-router' import { createFileRoute } from '@tanstack/react-router'
import { pb } from "@/lib/pocketbase"; import { pb } from "@/lib/pocketbase";
import { AutoSaveTextarea } from "@/components/AutoSaveTextarea"; import { AutoSaveTextarea } from "@/components/AutoSaveTextarea";
import { useState } from "react";
export const Route = createFileRoute( export const Route = createFileRoute(
'/_authenticated/document/$documentId', '/_authenticated/document/$documentId',
)({ )({
loader: async ({ params }) => { loader: async ({ params }) => {
const doc = await pb.collection("documents").getOne(params.documentId); const doc = await pb.collection("documents").getOne(params.documentId);
// Fetch relationships where this document is the primary and type is "plannedSecrets" // Fetch the unique relationship where this document is the primary and type is "plannedSecrets"
const relationships = await pb.collection("relationships").getFullList({ const relationships = await pb.collection("relationships").getList(1, 1, {
filter: `primary = "${params.documentId}" && type = "plannedSecrets"`, filter: `primary = "${params.documentId}" && type = "plannedSecrets"`,
}); });
// Get all related secret document IDs from the secondary field // Get all related secret document IDs from the secondary field
const secretIds = relationships.map((rel: any) => rel.secondary); const secretIds = relationships.items.length > 0 ? relationships.items[0].secondary : [];
// Fetch all related secret documents // Fetch all related secret documents
let secrets: any[] = []; let secrets: any[] = [];
if (secretIds.length > 0) { if (Array.isArray(secretIds) && secretIds.length > 0) {
secrets = await pb.collection("documents").getFullList({ secrets = await pb.collection("documents").getFullList({
filter: secretIds.map(id => `id = "${id}"`).join(" || "), filter: secretIds.map(id => `id = "${id}"`).join(" || "),
}); });
@@ -28,6 +29,10 @@ export const Route = createFileRoute(
function RouteComponent() { function RouteComponent() {
const { document, secrets } = Route.useLoaderData(); const { document, secrets } = Route.useLoaderData();
const strongStart = document?.data?.session?.strongStart || ""; const strongStart = document?.data?.session?.strongStart || "";
const [newSecret, setNewSecret] = useState("");
const [adding, setAdding] = useState(false);
const [secretList, setSecretList] = useState(secrets);
const [error, setError] = useState<string | null>(null);
async function handleSaveStrongStart(newValue: string) { async function handleSaveStrongStart(newValue: string) {
await pb.collection("documents").update(document.id, { await pb.collection("documents").update(document.id, {
@@ -41,6 +46,47 @@ function RouteComponent() {
}); });
} }
async function handleAddSecret() {
if (!newSecret.trim()) return;
setAdding(true);
setError(null);
try {
// 1. Create the secret document
const secretDoc = await pb.collection("documents").create({
campaign: document.campaign, // assuming campaign is an id or object
data: {
secret: {
text: newSecret,
discoveredOn: null,
},
},
});
// 2. Check for existing relationship
const existing = await pb.collection("relationships").getOne({
filter: `primary = "${document.id}" && type = "plannedSecrets"`,
});
if (existing.length > 0) {
// Update existing relationship to add new secret to secondary array
await pb.collection("relationships").update(existing[0].id, {
"+secondary": secretDoc.id,
});
} else {
// Create new relationship
await pb.collection("relationships").create({
primary: document.id,
secondary: [secretDoc.id],
type: "plannedSecrets",
});
}
setSecretList([...secretList, secretDoc]);
setNewSecret("");
} catch (e: any) {
setError(e?.message || "Failed to add secret.");
} finally {
setAdding(false);
}
}
return ( return (
<div className="max-w-xl mx-auto py-8"> <div className="max-w-xl mx-auto py-8">
<h2 className="text-2xl font-bold mb-4 text-slate-100">Session Strong Start</h2> <h2 className="text-2xl font-bold mb-4 text-slate-100">Session Strong Start</h2>
@@ -51,9 +97,9 @@ function RouteComponent() {
aria-label="Strong Start" aria-label="Strong Start"
/> />
<h3 className="text-lg font-semibold mt-8 mb-2 text-slate-200">Planned Secrets</h3> <h3 className="text-lg font-semibold mt-8 mb-2 text-slate-200">Planned Secrets</h3>
{secrets && secrets.length > 0 ? ( {secretList && secretList.length > 0 ? (
<ul className="space-y-2"> <ul className="space-y-2">
{secrets.map((secret: any) => ( {secretList.map((secret: any) => (
<li key={secret.id} className="bg-slate-800 rounded p-4 text-slate-100"> <li key={secret.id} className="bg-slate-800 rounded p-4 text-slate-100">
{secret.data?.secret?.text || <span className="italic text-slate-400">(No secret text)</span>} {secret.data?.secret?.text || <span className="italic text-slate-400">(No secret text)</span>}
</li> </li>
@@ -62,6 +108,27 @@ function RouteComponent() {
) : ( ) : (
<div className="text-slate-400">No planned secrets for this session.</div> <div className="text-slate-400">No planned secrets for this session.</div>
)} )}
<form
className="flex items-center gap-2 mt-4"
onSubmit={e => { e.preventDefault(); handleAddSecret(); }}
>
<input
type="text"
className="flex-1 px-3 py-2 rounded bg-slate-800 text-slate-100 border border-slate-700 focus:outline-none focus:ring-2 focus:ring-violet-500"
placeholder="Add a new secret..."
value={newSecret}
onChange={e => setNewSecret(e.target.value)}
disabled={adding}
/>
<button
type="submit"
className="px-4 py-2 rounded bg-emerald-600 hover:bg-emerald-700 text-white font-semibold transition-colors disabled:opacity-60"
disabled={adding || !newSecret.trim()}
>
{adding ? "Adding..." : "Add Secret"}
</button>
</form>
{error && <div className="text-red-400 mt-2 text-sm">{error}</div>}
</div> </div>
); );
} }