feat(naming): add Suggest Names button for ideas and tee compositor
This commit is contained in:
1 parent
25d24a53a6
commit
6c6867b49c
6 files changed
+276
-7
No files matched your search
@@ -812,10 +812,96 @@ async function openIdeaDrawer(id, initialTab = "details") {
|
||||
function closeIdeaDrawer() {
|
||||
state.activeIdeaId = null;
|
||||
state.activeIdea = null;
|
||||
document.getElementById("drawer-name-suggestions-panel")?.classList.add("hidden");
|
||||
document.getElementById("drawer-backdrop").classList.add("hidden");
|
||||
document.getElementById("idea-drawer").classList.add("hidden");
|
||||
}
|
||||
|
||||
async function requestNameSuggestionsForActiveIdea() {
|
||||
if (!state.activeIdeaId || !state.activeIdea) return;
|
||||
const panel = document.getElementById("drawer-name-suggestions-panel");
|
||||
const btn = document.getElementById("btn-suggest-names");
|
||||
if (!panel) return;
|
||||
|
||||
panel.classList.remove("hidden");
|
||||
panel.innerHTML = `<div class="muted-label" style="padding:0.4rem;">✨ Brainstorming 6 creative names & taglines for "${escapeHtml(state.activeIdea.title)}"...</div>`;
|
||||
if (btn) btn.disabled = true;
|
||||
|
||||
try {
|
||||
const res = await apiFetch(`/api/ideas/${state.activeIdeaId}/suggest-names`, {
|
||||
method: "POST"
|
||||
});
|
||||
const list = res.suggestions || [];
|
||||
panel.innerHTML = `
|
||||
<div class="name-suggestions-header">
|
||||
<span>✨ <strong>Suggested Names & Taglines</strong> <small class="muted-label">(${escapeHtml(res.generatorUsed || "AI")})</small></span>
|
||||
<div style="display:flex;gap:0.35rem;">
|
||||
<button type="button" id="btn-resuggest-names" class="btn btn-ghost btn-xs">🔄 More</button>
|
||||
<button type="button" id="btn-close-name-suggestions" class="btn btn-ghost btn-xs">✕</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="name-suggestions-grid">
|
||||
${list
|
||||
.map(
|
||||
(s, idx) => `
|
||||
<div class="name-suggestion-card" data-idx="${idx}">
|
||||
<div style="display:flex;justify-content:space-between;align-items:center;gap:0.35rem;">
|
||||
<strong style="font-size:0.86rem;color:var(--text-primary);">${escapeHtml(s.name)}</strong>
|
||||
<span class="tag-chip">${escapeHtml(s.style || "Name")}</span>
|
||||
</div>
|
||||
${s.tagline ? `<small class="muted-label" style="display:block;">${escapeHtml(s.tagline)}</small>` : ""}
|
||||
<div style="display:flex;gap:0.35rem;margin-top:0.25rem;flex-wrap:wrap;">
|
||||
<button type="button" class="btn btn-primary btn-xs btn-use-suggested-title" data-name="${escapeHtml(s.name)}" data-tagline="${escapeHtml(s.tagline || "")}">
|
||||
✓ Use Title
|
||||
</button>
|
||||
<button type="button" class="btn btn-ghost btn-xs btn-use-suggested-tee" data-name="${escapeHtml(s.name)}" data-tagline="${escapeHtml(s.tagline || "")}">
|
||||
👕 Send to Tee Canvas
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
)
|
||||
.join("")}
|
||||
</div>
|
||||
`;
|
||||
|
||||
panel.querySelector("#btn-resuggest-names")?.addEventListener("click", requestNameSuggestionsForActiveIdea);
|
||||
panel.querySelector("#btn-close-name-suggestions")?.addEventListener("click", () => {
|
||||
panel.classList.add("hidden");
|
||||
});
|
||||
|
||||
panel.querySelectorAll(".btn-use-suggested-title").forEach((b) => {
|
||||
b.addEventListener("click", async () => {
|
||||
const newTitle = b.dataset.name;
|
||||
const tagline = b.dataset.tagline;
|
||||
const patch = { title: newTitle };
|
||||
if (tagline && !state.activeIdea.elevator_pitch) {
|
||||
patch.elevator_pitch = tagline;
|
||||
}
|
||||
document.getElementById("drawer-title-input").value = newTitle;
|
||||
await saveActiveIdeaPatch(patch);
|
||||
showToast(`✨ Renamed Spark to "${newTitle}"!`);
|
||||
});
|
||||
});
|
||||
|
||||
panel.querySelectorAll(".btn-use-suggested-tee").forEach((b) => {
|
||||
b.addEventListener("click", () => {
|
||||
const topEl = document.getElementById("comp-top-text");
|
||||
const botEl = document.getElementById("comp-bottom-text");
|
||||
if (topEl) topEl.value = b.dataset.name.toUpperCase();
|
||||
if (botEl && b.dataset.tagline) botEl.value = b.dataset.tagline.toUpperCase();
|
||||
switchDrawerTab("mockup");
|
||||
renderCompositorCanvas();
|
||||
showToast("👕 Loaded name & tagline onto the T-Shirt Compositor!");
|
||||
});
|
||||
});
|
||||
} catch (err) {
|
||||
panel.innerHTML = `<div class="muted-label">⚠️ ${escapeHtml(err.message)}</div>`;
|
||||
} finally {
|
||||
if (btn) btn.disabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
function switchDrawerTab(tabName) {
|
||||
state.drawerTab = tabName;
|
||||
document.querySelectorAll(".drawer-tab").forEach((btn) => {
|
||||
@@ -1889,6 +1975,8 @@ function bindGlobalEvents() {
|
||||
document.getElementById("drawer-title-input")?.addEventListener("change", (e) => {
|
||||
saveActiveIdeaPatch({ title: e.target.value });
|
||||
});
|
||||
document.getElementById("btn-suggest-names")?.addEventListener("click", requestNameSuggestionsForActiveIdea);
|
||||
document.getElementById("btn-comp-suggest-names")?.addEventListener("click", requestNameSuggestionsForActiveIdea);
|
||||
document.getElementById("drawer-status-select")?.addEventListener("change", (e) => {
|
||||
saveActiveIdeaPatch({ status: e.target.value });
|
||||
});
|
||||
|
||||
+11
-2
@@ -347,7 +347,13 @@
|
||||
<aside id="idea-drawer" class="idea-drawer hidden" aria-label="Idea Workbench">
|
||||
<div class="drawer-header">
|
||||
<div class="drawer-title-group">
|
||||
<input type="text" id="drawer-title-input" class="drawer-title-input" placeholder="Idea Title" />
|
||||
<div class="drawer-title-row">
|
||||
<input type="text" id="drawer-title-input" class="drawer-title-input" placeholder="Idea Title" />
|
||||
<button type="button" id="btn-suggest-names" class="btn btn-secondary btn-xs" title="Brainstorm 6 creative names & taglines for this idea">
|
||||
✨ Suggest Names
|
||||
</button>
|
||||
</div>
|
||||
<div id="drawer-name-suggestions-panel" class="name-suggestions-panel hidden"></div>
|
||||
<div class="drawer-meta-row">
|
||||
<select id="drawer-status-select" class="drawer-select">
|
||||
<option value="spark">✨ Spark</option>
|
||||
@@ -647,7 +653,10 @@
|
||||
|
||||
<div class="form-row-2">
|
||||
<div>
|
||||
<label for="comp-top-text">Top Headline / Club Name</label>
|
||||
<div class="field-header-row">
|
||||
<label for="comp-top-text">Top Headline / Club Name</label>
|
||||
<button type="button" id="btn-comp-suggest-names" class="btn btn-ghost btn-xs">✨ Suggest Names</button>
|
||||
</div>
|
||||
<input type="text" id="comp-top-text" class="text-input input-sm" placeholder="HIGH ALTITUDE CLUB" />
|
||||
</div>
|
||||
<div>
|
||||
|
||||
@@ -885,6 +885,46 @@ body {
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.drawer-title-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.name-suggestions-panel {
|
||||
background: var(--bg-elevated);
|
||||
border: 1px solid var(--border-strong);
|
||||
border-radius: var(--radius-md);
|
||||
padding: 0.7rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.55rem;
|
||||
}
|
||||
|
||||
.name-suggestions-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
font-size: 0.82rem;
|
||||
}
|
||||
|
||||
.name-suggestions-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.name-suggestion-card {
|
||||
background: var(--bg-surface);
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: var(--radius-sm);
|
||||
padding: 0.55rem 0.65rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.25rem;
|
||||
}
|
||||
|
||||
.drawer-title-input {
|
||||
width: 100%;
|
||||
font-size: 1.25rem;
|
||||
|
||||
Reference in new issue
Block a user