feat(plan): Start planning button on project view
This commit is contained in:
@@ -3,6 +3,7 @@ import { ref, computed, onMounted, watch } from "vue";
|
||||
import { useRoute, useRouter } from "vue-router";
|
||||
import { apiGet, apiPatch, apiDelete, apiPost } from "@/api/client";
|
||||
import { useToastStore } from "@/stores/toast";
|
||||
import { useTasksStore } from "@/stores/tasks";
|
||||
import { relativeTime } from "@/composables/useRelativeTime";
|
||||
import ShareDialog from "@/components/ShareDialog.vue";
|
||||
import ProjectRulesTab from "@/components/rules/ProjectRulesTab.vue";
|
||||
@@ -62,9 +63,28 @@ interface NoteItem {
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
const toast = useToastStore();
|
||||
const tasksStore = useTasksStore();
|
||||
|
||||
const project = ref<Project | null>(null);
|
||||
const loading = ref(false);
|
||||
|
||||
const showStartPlanning = ref(false);
|
||||
const planTitle = ref("");
|
||||
const planningBusy = ref(false);
|
||||
|
||||
async function confirmStartPlanning() {
|
||||
const title = planTitle.value.trim();
|
||||
if (!title || !project.value) return;
|
||||
planningBusy.value = true;
|
||||
try {
|
||||
const result = await tasksStore.startPlanning(project.value.id, title);
|
||||
planTitle.value = "";
|
||||
showStartPlanning.value = false;
|
||||
router.push(`/tasks/${result.task.id}`);
|
||||
} finally {
|
||||
planningBusy.value = false;
|
||||
}
|
||||
}
|
||||
const saving = ref(false);
|
||||
const error = ref<string | null>(null);
|
||||
|
||||
@@ -340,12 +360,35 @@ async function confirmDelete() {
|
||||
<div class="page-header">
|
||||
<router-link to="/projects" class="btn-back">← Projects</router-link>
|
||||
<div class="page-header-actions">
|
||||
<router-link v-if="project" :to="`/workspace/${project.id}`" class="btn-workspace">
|
||||
<template v-if="showStartPlanning">
|
||||
<input
|
||||
v-model="planTitle"
|
||||
class="plan-title-input"
|
||||
placeholder="Plan title…"
|
||||
@keyup.enter="confirmStartPlanning"
|
||||
/>
|
||||
<button
|
||||
class="btn-workspace"
|
||||
:disabled="!planTitle.trim() || planningBusy"
|
||||
@click="confirmStartPlanning"
|
||||
>
|
||||
Create plan
|
||||
</button>
|
||||
<button class="btn-share" @click="showStartPlanning = false; planTitle = ''">Cancel</button>
|
||||
</template>
|
||||
<button
|
||||
v-else-if="project"
|
||||
class="btn-workspace"
|
||||
@click="showStartPlanning = true"
|
||||
>
|
||||
Start planning
|
||||
</button>
|
||||
<router-link v-if="project && !showStartPlanning" :to="`/workspace/${project.id}`" class="btn-workspace">
|
||||
<LayoutGrid :size="16" />
|
||||
Workspace
|
||||
</router-link>
|
||||
<button v-if="project" class="btn-share" @click="showShare = true">Share</button>
|
||||
<button v-if="project" class="btn-danger-outline" @click="showDeleteConfirm = true">Delete</button>
|
||||
<button v-if="project && !showStartPlanning" class="btn-share" @click="showShare = true">Share</button>
|
||||
<button v-if="project && !showStartPlanning" class="btn-danger-outline" @click="showDeleteConfirm = true">Delete</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -685,6 +728,15 @@ async function confirmDelete() {
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
.page-header-actions { display: flex; gap: 0.5rem; align-items: center; }
|
||||
.plan-title-input {
|
||||
background: var(--color-bg, #111113);
|
||||
color: inherit;
|
||||
border: 1px solid var(--color-border, #2a2a2e);
|
||||
border-radius: 6px;
|
||||
padding: 0.4rem 0.6rem;
|
||||
font: inherit;
|
||||
min-width: 200px;
|
||||
}
|
||||
|
||||
.btn-back {
|
||||
display: inline-flex;
|
||||
|
||||
Reference in New Issue
Block a user