Skip to content

Commit 725923b

Browse files
committed
feat: allow deleting entries from calendar
1 parent 2480198 commit 725923b

File tree

5 files changed

+54
-11
lines changed

5 files changed

+54
-11
lines changed

apps/backend/db/migrations/.snapshot-postgres.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -558,7 +558,7 @@
558558
"unsigned": false,
559559
"autoincrement": false,
560560
"primary": false,
561-
"nullable": false,
561+
"nullable": true,
562562
"mappedType": "integer"
563563
}
564564
},
@@ -607,6 +607,7 @@
607607
"id"
608608
],
609609
"referencedTableName": "public.entry",
610+
"deleteRule": "cascade",
610611
"updateRule": "cascade"
611612
}
612613
},
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { Migration } from "@mikro-orm/migrations";
2+
3+
export class Migration20241210094456 extends Migration {
4+
override async up(): Promise<void> {
5+
this.addSql(`alter table "entry_language" drop constraint "entry_language_entry_id_foreign";`);
6+
7+
this.addSql(`alter table "entry_language" alter column "entry_id" type int using ("entry_id"::int);`);
8+
this.addSql(`alter table "entry_language" alter column "entry_id" drop not null;`);
9+
this.addSql(
10+
`alter table "entry_language" add constraint "entry_language_entry_id_foreign" foreign key ("entry_id") references "entry" ("id") on update cascade on delete cascade;`
11+
);
12+
}
13+
14+
override async down(): Promise<void> {
15+
this.addSql(`alter table "entry_language" drop constraint "entry_language_entry_id_foreign";`);
16+
17+
this.addSql(`alter table "entry_language" alter column "entry_id" type int using ("entry_id"::int);`);
18+
this.addSql(`alter table "entry_language" alter column "entry_id" set not null;`);
19+
this.addSql(
20+
`alter table "entry_language" add constraint "entry_language_entry_id_foreign" foreign key ("entry_id") references "entry" ("id") on update cascade;`
21+
);
22+
}
23+
}

apps/backend/src/research/entry-languages/entry-language.entity.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Check, Entity, ManyToOne, Property } from "@mikro-orm/core";
1+
import { Cascade, Check, Entity, ManyToOne, Property } from "@mikro-orm/core";
22
import { BaseEntity } from "../../common/entities/base.entity";
33
import { Language } from "../../defaults/languages/language.entity";
44
import { Entry } from "../entries/entry.entity";
@@ -12,6 +12,6 @@ export class EntryLanguage extends BaseEntity {
1212
@ManyToOne()
1313
language!: Language;
1414

15-
@ManyToOne()
15+
@ManyToOne({ cascade: [Cascade.ALL] })
1616
entry!: Entry;
1717
}

apps/frontend/src/components/questionnaire/calendar/EntryForm.tsx

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@ export type EntryFormValues = {
1818
};
1919

2020
const messages = i18n("entityForm", {
21-
addDialectAction: "Add dialect",
21+
actionAddDialect: "Add dialect",
22+
actionDelete: "Delete",
2223
labelCarer: "Carer",
2324
labelLanguage: "Language",
2425
validationRatio: "Ratio must be between 1 and 100.",
@@ -28,11 +29,12 @@ const messages = i18n("entityForm", {
2829

2930
type EntityFormProps = {
3031
onSave: (entity: EntryFormValues) => void;
32+
onDelete?: () => void;
3133
entry?: Partial<EntryFormValues>;
3234
actionLabel: string;
3335
};
3436

35-
export function EntityForm({ onSave, actionLabel, entry }: EntityFormProps) {
37+
export function EntityForm({ onSave, onDelete, actionLabel, entry }: EntityFormProps) {
3638
const t = useStore(messages);
3739
const f = useForm<EntryFormValues>({
3840
initialValues: {
@@ -121,15 +123,22 @@ export function EntityForm({ onSave, actionLabel, entry }: EntityFormProps) {
121123
}}
122124
variant="light"
123125
>
124-
{t.addDialectAction}
126+
{t.actionAddDialect}
125127
</Button>
126128
<Group>
127129
<TimeInput flex={1} {...f.getInputProps("startedAt")} />
128130
-
129131
<TimeInput flex={1} {...f.getInputProps("endedAt")} />
130132
</Group>
131133

132-
<Button type="submit">{actionLabel}</Button>
134+
<Group justify="flex-end">
135+
{onDelete && (
136+
<Button onClick={onDelete} variant="outline" color="uzhOrange">
137+
{t.actionDelete}
138+
</Button>
139+
)}
140+
<Button type="submit">{actionLabel}</Button>
141+
</Group>
133142
</Stack>
134143
</form>
135144
);

apps/frontend/src/routes/_auth/questionnaire/_questionnaire/$id/entries.tsx

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ function QuestionnaireEntries() {
4747

4848
const createMutation = $api.useMutation("post", "/entries");
4949
const updateMutation = $api.useMutation("patch", "/entries/{id}");
50+
const deleteMutation = $api.useMutation("delete", "/entries/{id}");
5051
const { data: questionnaire, refetch } = $api.useSuspenseQuery("get", "/questionnaires/{id}", { params: { path: { id: p.id } } });
5152

5253
const events: ExtendedEvent[] =
@@ -59,7 +60,7 @@ function QuestionnaireEntries() {
5960
backgroundColor: theme.colors[theme.primaryColor][4],
6061
})) ?? [];
6162

62-
const handleReset = () => {
63+
const reset = () => {
6364
refetch();
6465
close();
6566
setSelectedWeekday(undefined);
@@ -76,7 +77,7 @@ function QuestionnaireEntries() {
7677
questionnaire: questionnaire.id,
7778
};
7879

79-
createMutation.mutate({ body: entryRequest }, { onSuccess: handleReset });
80+
createMutation.mutate({ body: entryRequest }, { onSuccess: reset });
8081
};
8182

8283
const handleUpdate = (id: number, { carer, ...rest }: Partial<EntryFormValues>, weekday?: number) => {
@@ -87,7 +88,11 @@ function QuestionnaireEntries() {
8788
questionnaire: questionnaire.id,
8889
};
8990

90-
updateMutation.mutate({ body: entryRequest, params: { path: { id: id.toString() } } }, { onSuccess: handleReset });
91+
updateMutation.mutate({ body: entryRequest, params: { path: { id: id.toString() } } }, { onSuccess: reset });
92+
};
93+
94+
const handleDelete = (id: number) => {
95+
deleteMutation.mutate({ params: { path: { id: id.toString() } } }, { onSuccess: reset });
9196
};
9297

9398
const handleOnSave = (entry: EntryFormValues | Partial<EntryFormValues>) => {
@@ -105,7 +110,12 @@ function QuestionnaireEntries() {
105110
return (
106111
<>
107112
<Modal opened={opened} onClose={close} size="md">
108-
<EntityForm onSave={handleOnSave} entry={entryDraft} actionLabel={t.addEntityLabel} />
113+
<EntityForm
114+
onSave={handleOnSave}
115+
onDelete={entryUpdatingId ? () => handleDelete(entryUpdatingId) : undefined}
116+
entry={entryDraft}
117+
actionLabel={t.addEntityLabel}
118+
/>
109119
</Modal>
110120
<form onSubmit={handleSubmit}>
111121
<Stack>

0 commit comments

Comments
 (0)