Skip to content

Commit 97e137c

Browse files
authored
feat: add support for create + add more for all create modals and support k… (#526)
* add support for create + add more for all create modals and support keyboard bindings * listen for esc to close modals Former-commit-id: 22bbaae
1 parent 0de6c23 commit 97e137c

File tree

4 files changed

+124
-33
lines changed

4 files changed

+124
-33
lines changed

frontend/components/Base/Modal.vue

+14
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,12 @@
3232
},
3333
});
3434
35+
function escClose(e: KeyboardEvent) {
36+
if (e.key === "Escape") {
37+
close();
38+
}
39+
}
40+
3541
function close() {
3642
if (props.readonly) {
3743
emit("cancel");
@@ -42,4 +48,12 @@
4248
4349
const modalId = useId();
4450
const modal = useVModel(props, "modelValue", emit);
51+
52+
watchEffect(() => {
53+
if (modal.value) {
54+
document.addEventListener("keydown", escClose);
55+
} else {
56+
document.removeEventListener("keydown", escClose);
57+
}
58+
});
4559
</script>

frontend/components/Item/CreateModal.vue

+34-21
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,14 @@
11
<template>
22
<BaseModal v-model="modal">
33
<template #title> Create Item </template>
4-
<form @submit.prevent="create(true)">
4+
<div @keyup="keySubmit">
55
<LocationSelector v-model="form.location" />
6-
<FormTextField
7-
ref="locationNameRef"
8-
v-model="form.name"
9-
:trigger-focus="focused"
10-
:autofocus="true"
11-
label="Item Name"
12-
/>
6+
<FormTextField ref="nameInput" v-model="form.name" :trigger-focus="focused" :autofocus="true" label="Item Name" />
137
<FormTextArea v-model="form.description" label="Item Description" />
148
<FormMultiselect v-model="form.labels" label="Labels" :items="labels ?? []" />
159
<div class="modal-action">
1610
<div class="flex justify-center">
17-
<BaseButton ref="submitBtn" type="submit" class="rounded-r-none" :loading="loading">
11+
<BaseButton class="rounded-r-none" :loading="loading" @click="create(true)">
1812
<template #icon>
1913
<Icon name="mdi-package-variant" class="swap-off h-5 w-5" />
2014
<Icon name="mdi-package-variant-closed" class="swap-on h-5 w-5" />
@@ -26,12 +20,17 @@
2620
<Icon class="h-5 w-5" name="mdi-chevron-down" />
2721
</label>
2822
<ul tabindex="0" class="dropdown-content menu p-2 shadow bg-base-100 rounded-box w-64">
29-
<li><button @click.prevent="create(false)">Create and Add Another</button></li>
23+
<li>
24+
<button type="button" @click.prevent="create(false)">Create and Add Another</button>
25+
</li>
3026
</ul>
3127
</div>
3228
</div>
3329
</div>
34-
</form>
30+
</div>
31+
<p class="text-sm text-center mt-4">
32+
use <kbd class="kbd kbd-xs">Shift</kbd> + <kbd class="kbd kbd-xs"> Enter </kbd> to create and add another
33+
</p>
3534
</BaseModal>
3635
</template>
3736

@@ -47,6 +46,15 @@
4746
},
4847
});
4948
49+
const api = useUserApi();
50+
const toast = useNotifier();
51+
52+
const locationsStore = useLocationStore();
53+
const locations = computed(() => locationsStore.allLocations);
54+
55+
const labelStore = useLabelStore();
56+
const labels = computed(() => labelStore.labels);
57+
5058
const route = useRoute();
5159
5260
const labelId = computed(() => {
@@ -63,16 +71,7 @@
6371
return null;
6472
});
6573
66-
const api = useUserApi();
67-
const toast = useNotifier();
68-
69-
const locationsStore = useLocationStore();
70-
const locations = computed(() => locationsStore.allLocations);
71-
72-
const labelStore = useLabelStore();
73-
const labels = computed(() => labelStore.labels);
74-
75-
const submitBtn = ref(null);
74+
const nameInput = ref<HTMLInputElement | null>(null);
7675
7776
const modal = useVModel(props, "modelValue");
7877
const loading = ref(false);
@@ -136,4 +135,18 @@
136135
navigateTo(`/item/${data.id}`);
137136
}
138137
}
138+
139+
async function keySubmit(e: KeyboardEvent) {
140+
// Shift + Enter
141+
if (e.shiftKey && e.key === "Enter") {
142+
console.log("Shift + Enter");
143+
e.preventDefault();
144+
await create(false);
145+
focused.value = true;
146+
} else if (e.key === "Enter") {
147+
e.preventDefault();
148+
console.log("Enter");
149+
await create(true);
150+
}
151+
}
139152
</script>

frontend/components/Label/CreateModal.vue

+38-6
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<template>
22
<BaseModal v-model="modal">
33
<template #title> Create Label </template>
4-
<form @submit.prevent="create">
4+
<div @keyup="keySubmit">
55
<FormTextField
66
ref="locationNameRef"
77
v-model="form.name"
@@ -11,9 +11,26 @@
1111
/>
1212
<FormTextArea v-model="form.description" label="Label Description" />
1313
<div class="modal-action">
14-
<BaseButton type="submit" :loading="loading"> Create </BaseButton>
14+
<div class="flex justify-center">
15+
<BaseButton class="rounded-r-none" type="submit" :loading="loading" @click.prevent="create(true)">
16+
Create
17+
</BaseButton>
18+
<div class="dropdown dropdown-top">
19+
<label tabindex="0" class="btn rounded-l-none rounded-r-xl">
20+
<Icon class="h-5 w-5" name="mdi-chevron-down" />
21+
</label>
22+
<ul tabindex="0" class="dropdown-content menu p-2 shadow bg-base-100 rounded-box w-64">
23+
<li>
24+
<button @click.prevent="create(false)">Create and Add Another</button>
25+
</li>
26+
</ul>
27+
</div>
28+
</div>
1529
</div>
16-
</form>
30+
</div>
31+
<p class="text-sm text-center mt-4">
32+
use <kbd class="kbd kbd-xs">Shift</kbd> + <kdb class="kbd kbd-xs"> Enter </kdb> to create and add another
33+
</p>
1734
</BaseModal>
1835
</template>
1936

@@ -39,7 +56,6 @@
3956
form.description = "";
4057
form.color = "";
4158
focused.value = false;
42-
modal.value = false;
4359
loading.value = false;
4460
}
4561
@@ -53,7 +69,7 @@
5369
const api = useUserApi();
5470
const toast = useNotifier();
5571
56-
async function create() {
72+
async function create(close: boolean) {
5773
const { error, data } = await api.labels.create(form);
5874
if (error) {
5975
toast.error("Couldn't create label");
@@ -62,6 +78,22 @@
6278
6379
toast.success("Label created");
6480
reset();
65-
navigateTo(`/label/${data.id}`);
81+
82+
if (close) {
83+
modal.value = false;
84+
navigateTo(`/label/${data.id}`);
85+
}
86+
}
87+
88+
async function keySubmit(e: KeyboardEvent) {
89+
// Shift + Enter
90+
if (e.shiftKey && e.key === "Enter") {
91+
e.preventDefault();
92+
await create(false);
93+
focused.value = true;
94+
} else if (e.key === "Enter") {
95+
e.preventDefault();
96+
await create(true);
97+
}
6698
}
6799
</script>

frontend/components/Location/CreateModal.vue

+38-6
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<template>
22
<BaseModal v-model="modal">
33
<template #title> Create Location </template>
4-
<form @submit.prevent="create">
4+
<div @keyup="keySubmit">
55
<FormTextField
66
ref="locationNameRef"
77
v-model="form.name"
@@ -12,9 +12,26 @@
1212
<FormTextArea v-model="form.description" label="Location Description" />
1313
<LocationSelector v-model="form.parent" />
1414
<div class="modal-action">
15-
<BaseButton type="submit" :loading="loading"> Create </BaseButton>
15+
<div class="flex justify-center">
16+
<BaseButton class="rounded-r-none" type="submit" :loading="loading" @click="create(true)">
17+
Create
18+
</BaseButton>
19+
<div class="dropdown dropdown-top">
20+
<label tabindex="0" class="btn rounded-l-none rounded-r-xl">
21+
<Icon class="h-5 w-5" name="mdi-chevron-down" />
22+
</label>
23+
<ul tabindex="0" class="dropdown-content menu p-2 shadow bg-base-100 rounded-box w-64">
24+
<li>
25+
<button @click.prevent="create(false)">Create and Add Another</button>
26+
</li>
27+
</ul>
28+
</div>
29+
</div>
1630
</div>
17-
</form>
31+
</div>
32+
<p class="text-sm text-center mt-4">
33+
use <kbd class="kbd kbd-xs">Shift</kbd> + <kbd class="kbd kbd-xs"> Enter </kbd> to create and add another
34+
</p>
1835
</BaseModal>
1936
</template>
2037

@@ -48,14 +65,13 @@
4865
form.description = "";
4966
form.parent = null;
5067
focused.value = false;
51-
modal.value = false;
5268
loading.value = false;
5369
}
5470
5571
const api = useUserApi();
5672
const toast = useNotifier();
5773
58-
async function create() {
74+
async function create(close: boolean) {
5975
loading.value = true;
6076
6177
const { data, error } = await api.locations.create({
@@ -72,6 +88,22 @@
7288
toast.success("Location created");
7389
}
7490
reset();
75-
navigateTo(`/location/${data.id}`);
91+
92+
if (close) {
93+
modal.value = false;
94+
navigateTo(`/location/${data.id}`);
95+
}
96+
}
97+
98+
async function keySubmit(e: KeyboardEvent) {
99+
// Shift + Enter
100+
if (e.shiftKey && e.key === "Enter") {
101+
e.preventDefault();
102+
await create(false);
103+
focused.value = true;
104+
} else if (e.key === "Enter") {
105+
e.preventDefault();
106+
await create(true);
107+
}
76108
}
77109
</script>

0 commit comments

Comments
 (0)