Skip to content

Commit 31d7efa

Browse files
committed
added tag picker to query form; added habit query removal after break
1 parent a1d3580 commit 31d7efa

File tree

5 files changed

+44
-40
lines changed

5 files changed

+44
-40
lines changed

src/components/habit/form.tsx

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ import { AlertTriangle, Check, Loader2, X } from "lucide-react"
1616
import React from "react"
1717
import { toast } from "sonner"
1818

19+
import { TagPicker } from "../tag/picker"
20+
1921
interface P {
2022
value?: Habit
2123
onChange: (h: Habit) => Promise<unknown>
@@ -140,6 +142,14 @@ export const HabitForm: React.FC<P> = ({ value, onChange, onCancel }) => {
140142
/>
141143
</div>
142144

145+
<div className="flex flex-col gap-2">
146+
<Label>Tags</Label>
147+
<TagPicker
148+
value={habit.tagNames}
149+
onChange={(tags) => update((h) => (h.tagNames = tags))}
150+
/>
151+
</div>
152+
143153
<Separator />
144154

145155
<div className="flex flex-col items-center gap-2 justify-center">

src/components/habit/view.tsx

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,12 @@ import { Button } from "@/components/ui/button"
66
import { Label } from "@/components/ui/label"
77
import { Separator } from "@/components/ui/separator"
88
import { cn } from "@/lib/utils"
9-
import { Completion_ButtonOptionsSchema } from "@/proto/models/v1/models_pb"
10-
import { create } from "@bufbuild/protobuf"
9+
import { Completion_ButtonOptionsSchema, HabitSchema } from "@/proto/models/v1/models_pb"
10+
import { clone, create } from "@bufbuild/protobuf"
1111
import { Link } from "@tanstack/react-router"
1212
import { ChevronLeft, History, Pencil, RefreshCw, Trash2 } from "lucide-react"
1313
import React from "react"
14+
import { toast } from "sonner"
1415

1516
import { Page } from "../page/page"
1617
import { HabitBreakDialog } from "./break-dialog"
@@ -32,6 +33,15 @@ export const HabitView: React.FC = () => {
3233

3334
const historyURL = `https://github.com/${repo?.full_name}/commits/main/habits/${habit.name}.json`
3435

36+
const handleTagsChange = (tags: string[]) => {
37+
const copy = clone(HabitSchema, habit)
38+
copy.tagNames = [...tags].sort()
39+
40+
toast.promise(update.mutateAsync(copy), {
41+
error: (e: Error) => ({ message: "Habit update failed", description: e.message }),
42+
})
43+
}
44+
3545
let content = (
3646
<>
3747
<div className="flex items-center gap-2 flex-wrap">
@@ -83,7 +93,7 @@ export const HabitView: React.FC = () => {
8393

8494
<div className="flex flex-col gap-2">
8595
<Label className="text-muted-foreground/50">Tags</Label>
86-
<TagPicker />
96+
<TagPicker value={habit.tagNames} onChange={handleTagsChange} />
8797
</div>
8898

8999
<Separator />

src/components/tag/picker.tsx

Lines changed: 17 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import { useCollectionContext } from "@/components/collection/context"
2-
import { useHabitContext } from "@/components/habit/context"
32
import { Button } from "@/components/ui/button"
43
import {
54
Dialog,
@@ -8,23 +7,24 @@ import {
87
DialogFooter,
98
DialogTitle,
109
} from "@/components/ui/dialog"
11-
import { HabitSchema } from "@/proto/models/v1/models_pb"
12-
import { clone } from "@bufbuild/protobuf"
1310
import { DialogTrigger } from "@radix-ui/react-dialog"
1411
import { Link } from "@tanstack/react-router"
15-
import { Check, Ellipsis, Loader2, Plus, Undo2 } from "lucide-react"
12+
import { Check, Ellipsis, Plus, Undo2 } from "lucide-react"
1613
import React from "react"
17-
import { toast } from "sonner"
1814

1915
import { TagContext } from "./context"
2016
import { TagList } from "./list"
2117

22-
export const TagPicker: React.FC = () => {
18+
interface P {
19+
value: string[]
20+
onChange: (tags: string[]) => void
21+
}
22+
23+
export const TagPicker: React.FC<P> = ({ value, onChange }) => {
2324
const { tags } = useCollectionContext()
24-
const { habit, update } = useHabitContext()
2525

2626
const [open, setOpen] = React.useState(false)
27-
const [selected, setSelected] = React.useState<Set<string>>(new Set(habit.tagNames))
27+
const [selected, setSelected] = React.useState<Set<string>>(new Set(value))
2828

2929
const toggleTag = (name: string) => {
3030
const next = new Set(selected)
@@ -38,24 +38,19 @@ export const TagPicker: React.FC = () => {
3838

3939
const handleCancel = () => {
4040
setOpen(false)
41-
setSelected(new Set(habit.tagNames))
41+
setSelected(new Set(value))
4242
}
4343

4444
const handleSubmit = () => {
45-
const copy = clone(HabitSchema, habit)
46-
copy.tagNames = [...selected].sort()
47-
48-
toast.promise(
49-
update.mutateAsync(copy).then(() => setOpen(false)),
50-
{
51-
error: (e: Error) => ({ message: "Habit update failed", description: e.message }),
52-
},
53-
)
45+
const tags = [...selected]
46+
tags.sort()
47+
onChange(tags)
48+
setOpen(false)
5449
}
5550

5651
return (
5752
<div data-testid="tag-picker" className="flex items-center gap-1 flex-wrap">
58-
<TagList tags={habit.tagNames}>
53+
<TagList tags={value}>
5954
<TagContext value={{ active: selected, onClick: toggleTag }}>
6055
<Dialog open={open} onOpenChange={setOpen}>
6156
<DialogTrigger asChild>
@@ -86,24 +81,12 @@ export const TagPicker: React.FC = () => {
8681
<TagList tags={tags} />
8782
</div>
8883
<DialogFooter>
89-
<Button
90-
variant="outline"
91-
onClick={handleCancel}
92-
disabled={update.isPending}
93-
>
84+
<Button variant="outline" onClick={handleCancel}>
9485
<Undo2 />
9586
Cancel
9687
</Button>
97-
<Button
98-
variant="outline"
99-
disabled={update.isPending}
100-
onClick={handleSubmit}
101-
>
102-
{update.isPending ? (
103-
<Loader2 className="animate-spin" />
104-
) : (
105-
<Check className="text-emerald-600" />
106-
)}
88+
<Button variant="outline" onClick={handleSubmit}>
89+
<Check className="text-emerald-600" />
10790
Save
10891
</Button>
10992
</DialogFooter>

src/components/tag/view.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ export const TagView: React.FC<P> = ({ name, tag, preview }) => {
2525
}
2626

2727
return (
28-
<div
28+
<button
2929
data-testid={`tag-${name}`}
3030
onClick={() => ctx.onClick?.(name)}
3131
className={cn(
@@ -45,6 +45,6 @@ export const TagView: React.FC<P> = ({ name, tag, preview }) => {
4545
>
4646
{displayedName}
4747
</span>
48-
</div>
48+
</button>
4949
)
5050
}

src/lib/queries.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -296,7 +296,8 @@ export const useBreakHabit = () => {
296296
sha: habit.sha,
297297
})
298298
},
299-
onSettled: async () => {
299+
onSettled: async (_, __, habit) => {
300+
client.removeQueries({ queryKey: ["repo", repo.id, "habit", habit.name] })
300301
await client.invalidateQueries({ queryKey: ["repo", repo.id, "content"] })
301302
},
302303
retry: handleError("Failed to break a habit", { maxFailures: 0 }),

0 commit comments

Comments
 (0)