📦 chore: update [id]
swadhinbiswas committed 3 months ago
70ffd48
1 parent ccc338f
commit 70ffd48
1 file changed
+115 -0
Showing 1 changed file+115-0
▼src/pages/[owner]/[repo]/milestones/[id]/edit.astro
+115-0
| @@ -0,0 +1,115 @@ | ||
1 | +--- | |
2 | +import BaseLayout from "@/layouts/BaseLayout.astro"; | |
3 | +import { getDatabase, schema } from "@/db"; | |
4 | +import { eq, and } from "drizzle-orm"; | |
5 | + | |
6 | +const { owner: ownerName, repo: repoName, id } = Astro.params; | |
7 | +const db = getDatabase(); | |
8 | + | |
9 | +const user = await db.query.users.findFirst({ | |
10 | + where: eq(schema.users.username, ownerName!), | |
11 | +}); | |
12 | +if (!user) return Astro.redirect("/404"); | |
13 | + | |
14 | +const repoData = await db.query.repositories.findFirst({ | |
15 | + where: and( | |
16 | + eq(schema.repositories.ownerId, user.id), | |
17 | + eq(schema.repositories.name, repoName!), | |
18 | + ), | |
19 | + with: { owner: true }, | |
20 | +}); | |
21 | +if (!repoData) return Astro.redirect("/404"); | |
22 | + | |
23 | +const milestone = await db.query.milestones.findFirst({ | |
24 | + where: and( | |
25 | + eq(schema.milestones.id, id!), | |
26 | + eq(schema.milestones.repositoryId, repoData.id), | |
27 | + ), | |
28 | +}); | |
29 | +if (!milestone) return Astro.redirect(`/${ownerName}/${repoName}/milestones`); | |
30 | + | |
31 | +const dueDateStr = milestone.dueDate ? new Date(milestone.dueDate).toISOString().split('T')[0] : ''; | |
32 | +--- | |
33 | + | |
34 | +<BaseLayout title={`Edit Milestone · ${ownerName}/${repoName}`}> | |
35 | + <div class="container max-w-4xl py-8"> | |
36 | + <div class="mb-6"> | |
37 | + <a href={`/${ownerName}/${repoName}/milestones`} class="text-sm text-muted-foreground hover:text-foreground"> | |
38 | + ← Back to milestones | |
39 | + </a> | |
40 | + </div> | |
41 | + | |
42 | + <h1 class="text-2xl font-semibold mb-6">Edit Milestone</h1> | |
43 | + | |
44 | + <form id="edit-milestone-form" class="space-y-6"> | |
45 | + <div class="space-y-2"> | |
46 | + <label class="text-sm font-medium">Title</label> | |
47 | + <input | |
48 | + type="text" | |
49 | + name="title" | |
50 | + value={milestone.title} | |
51 | + required | |
52 | + class="w-full rounded-lg border border-border bg-background px-4 py-2.5 text-foreground focus:outline-none focus:ring-2 focus:ring-ring" | |
53 | + /> | |
54 | + </div> | |
55 | + | |
56 | + <div class="space-y-2"> | |
57 | + <label class="text-sm font-medium">Description</label> | |
58 | + <textarea | |
59 | + name="description" | |
60 | + rows={4} | |
61 | + class="w-full rounded-lg border border-border bg-background px-4 py-2.5 text-foreground focus:outline-none focus:ring-2 focus:ring-ring" | |
62 | + >{milestone.description || ''}</textarea> | |
63 | + </div> | |
64 | + | |
65 | + <div class="space-y-2"> | |
66 | + <label class="text-sm font-medium">Due Date</label> | |
67 | + <input | |
68 | + type="date" | |
69 | + name="dueDate" | |
70 | + value={dueDateStr} | |
71 | + class="w-full rounded-lg border border-border bg-background px-4 py-2.5 text-foreground focus:outline-none focus:ring-2 focus:ring-ring" | |
72 | + /> | |
73 | + </div> | |
74 | + | |
75 | + <div class="flex justify-end gap-3"> | |
76 | + <a | |
77 | + href={`/${ownerName}/${repoName}/milestones`} | |
78 | + class="px-4 py-2 rounded-lg border border-border bg-background text-sm text-muted-foreground hover:bg-accent" | |
79 | + > | |
80 | + Cancel | |
81 | + </a> | |
82 | + <button | |
83 | + type="submit" | |
84 | + class="px-4 py-2 rounded-lg bg-primary text-sm font-medium text-primary-foreground hover:opacity-90" | |
85 | + > | |
86 | + Save Changes | |
87 | + </button> | |
88 | + </div> | |
89 | + </form> | |
90 | + </div> | |
91 | + | |
92 | + <script define:vars={{ owner: ownerName, repo: repoName, milestoneId: id }}> | |
93 | + document.getElementById('edit-milestone-form')?.addEventListener('submit', async (e) => { | |
94 | + e.preventDefault(); | |
95 | + const formData = new FormData(e.target); | |
96 | + const data = { | |
97 | + title: formData.get('title'), | |
98 | + description: formData.get('description'), | |
99 | + dueDate: formData.get('dueDate') || null, | |
100 | + }; | |
101 | + | |
102 | + try { | |
103 | + const res = await fetch(`/api/repos/${owner}/${repo}/milestones/${milestoneId}`, { | |
104 | + method: 'PATCH', | |
105 | + headers: { 'Content-Type': 'application/json' }, | |
106 | + body: JSON.stringify(data), | |
107 | + }); | |
108 | + if (!res.ok) throw new Error('Failed'); | |
109 | + window.location.href = `/${owner}/${repo}/milestones`; | |
110 | + } catch (err) { | |
111 | + alert('Failed to update milestone'); | |
112 | + } | |
113 | + }); | |
114 | + </script> | |
115 | +</BaseLayout> | |
0 | 116 | |