feat(rulebook): RulesView three-pane shell + child panes + rule editor
This commit is contained in:
@@ -0,0 +1,80 @@
|
||||
<script setup lang="ts">
|
||||
import { ref } from "vue";
|
||||
import { useRulebooksStore } from "@/stores/rulebooks";
|
||||
import type { RulebookTopic } from "@/api/rulebooks";
|
||||
|
||||
const props = defineProps<{
|
||||
rulebookId: number;
|
||||
topics: RulebookTopic[];
|
||||
selectedTopicId: number | null;
|
||||
}>();
|
||||
const emit = defineEmits<{ "select-topic": [id: number] }>();
|
||||
|
||||
const store = useRulebooksStore();
|
||||
const isCreating = ref(false);
|
||||
const newTitle = ref("");
|
||||
|
||||
async function submitNew() {
|
||||
const title = newTitle.value.trim();
|
||||
if (!title) return;
|
||||
const topic = await store.createTopic(props.rulebookId, { title });
|
||||
newTitle.value = "";
|
||||
isCreating.value = false;
|
||||
emit("select-topic", topic.id);
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<section class="pane">
|
||||
<header><h2>Topics</h2></header>
|
||||
<ul>
|
||||
<li
|
||||
v-for="t in topics"
|
||||
:key="t.id"
|
||||
:class="{ active: t.id === selectedTopicId }"
|
||||
@click="emit('select-topic', t.id)"
|
||||
>
|
||||
{{ t.title }}
|
||||
</li>
|
||||
</ul>
|
||||
<div class="new-topic">
|
||||
<button v-if="!isCreating" @click="isCreating = true">+ New topic</button>
|
||||
<form v-else @submit.prevent="submitNew">
|
||||
<input v-model="newTitle" autofocus placeholder="Topic title (e.g. git-workflow)" />
|
||||
<div class="form-buttons">
|
||||
<button type="submit">Create</button>
|
||||
<button type="button" @click="isCreating = false">Cancel</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<!-- Subscription panel — populated in T14. -->
|
||||
<div class="subscriptions">
|
||||
<h3>Subscribers</h3>
|
||||
<p class="hint">(subscription management — populated in next task)</p>
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.pane { background: var(--color-surface, #18181b); padding: 1rem; overflow-y: auto; }
|
||||
header h2 { font-family: Fraunces, serif; font-style: italic; margin: 0 0 0.5rem 0; }
|
||||
ul { list-style: none; padding: 0; margin: 1rem 0; }
|
||||
li { padding: 0.5rem; cursor: pointer; border-radius: 6px; }
|
||||
li.active { background: var(--color-primary-bg, rgba(99,102,241,0.15)); }
|
||||
li:hover { background: var(--color-hover, rgba(255,255,255,0.05)); }
|
||||
.new-topic input {
|
||||
width: 100%; margin-bottom: 0.5rem;
|
||||
background: var(--color-bg, #111113); color: inherit;
|
||||
border: 1px solid var(--color-border, #2a2a2e); border-radius: 6px;
|
||||
padding: 0.5rem;
|
||||
}
|
||||
.form-buttons { display: flex; gap: 0.5rem; }
|
||||
.subscriptions {
|
||||
margin-top: 2rem;
|
||||
border-top: 1px solid var(--color-border, #2a2a2e);
|
||||
padding-top: 1rem;
|
||||
}
|
||||
.subscriptions h3 { font-size: 0.9em; opacity: 0.7; text-transform: uppercase; letter-spacing: 0.05em; }
|
||||
.hint { font-size: 0.85em; opacity: 0.6; }
|
||||
button { cursor: pointer; }
|
||||
</style>
|
||||
Reference in New Issue
Block a user