Skip to content

Commit

Permalink
feat(dashboard): split dialog and form of container creation
Browse files Browse the repository at this point in the history
  • Loading branch information
JustSamuel committed Jun 23, 2024
1 parent 3093b82 commit 6428a17
Show file tree
Hide file tree
Showing 5 changed files with 104 additions and 53 deletions.
5 changes: 4 additions & 1 deletion .eslintrc.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,10 @@ module.exports = {
'@intlify/vue-i18n/no-missing-keys': 'error',
'@intlify/vue-i18n/no-missing-keys-in-other-locales': 'error',
'@intlify/vue-i18n/no-unused-keys': ['error', { 'enableFix': true, 'extensions': ['.js', '.vue', '.ts'] }],
'@intlify/vue-i18n/no-duplicate-keys-in-locale': 'error'
'@intlify/vue-i18n/no-duplicate-keys-in-locale': 'error',
'vue/no-mutating-props': ['error', {
'shallowOnly': true
}]
},
ignorePatterns: ["/src/components/icons/*.vue", "package-lock.json"],
parserOptions: {
Expand Down
78 changes: 78 additions & 0 deletions apps/dashboard/src/components/container/ContainerActionForm.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
<template>
<form id="createForm" class="flex flex-column gap-3">
<div class="flex flex-row flex-wrap justify-content-between align-items-center">
<label for="name" class="mr-8">{{ $t('c_productContainerOperations.Name') }}</label>
<div class="relative">
<InputText id="name" class="w-18rem" v-model="form.model.name.value.value"
type="text" v-bind="form.model.name.attr.value"/>
<error-span :error="form.context.errors.value.name"/>
</div>
</div>
<div class="flex flex-row flex-wrap justify-content-between align-items-center">
<label for="owner" class="mr-8">
{{ $t('c_POSCreate.Owner') }}
<i class="pi pi-exclamation-circle text-red-500 cursor-pointer"
v-tooltip.top="$t('tooltip.owner_revenue')"/>
</label>
<div class="flex flex-column flex-end relative">
<div v-if="state.create">
<Dropdown :placeholder="$t('c_POSCreate.Select owner')" :options="organs" optionLabel="firstName"
v-model="form.model.owner.value.value" class="w-18rem" id="owner"
v-bind="form.model.owner.attr.value"/>
<error-span :error="form.context.errors.value.owner"/>
</div>
<div v-else-if="container">
<p class="my-0">{{ container.owner.firstName + ' ' + container.owner.lastName }}</p>
</div>
</div>
</div>
<div class="flex flex-row flex-wrap justify-content-between align-items-center">
<label for="name" class="mr-8">{{ $t('c_containerEditModal.Public') }}</label>
<div class="relative">
<Checkbox v-model="form.model.public.value.value" v-bind="form.model.public.attr.value"
inputId="publicContainer"
name="public" value="public" :binary="true"/>
<error-span :error="form.context.errors.value.public"/>
</div>
</div>
</form>
</template>

<script setup lang="ts">
import { type Form } from "@/utils/formUtil";
import { createContainerSpec } from "@/utils/validation-schema";
import InputText from "primevue/inputtext";
import ErrorSpan from "@/components/ErrorSpan.vue";
import Dropdown from "primevue/dropdown";
import { computed, type PropType, ref, type Ref } from "vue";
import type { ContainerWithProductsResponse } from "@sudosos/sudosos-client";
import { useI18n } from "vue-i18n";
import { useAuthStore } from "@sudosos/sudosos-frontend-common";
import { storeToRefs } from "pinia";
const { t } = useI18n();
const props = defineProps({
form: {
type: Object as Form<typeof createContainerSpec>,
required: true,
},
container: {
type: Object as PropType<ContainerWithProductsResponse>,
required: false,
},
});
const { organs } = storeToRefs(useAuthStore());
const state = computed(() => {
return {
create: props.container == undefined,
edit: props.container != undefined,
};
});
</script>

<style scoped lang="scss">
</style>
62 changes: 12 additions & 50 deletions apps/dashboard/src/components/container/ContainerActionsDialog.vue
Original file line number Diff line number Diff line change
Expand Up @@ -8,68 +8,31 @@
ref="dialog"
@show="openDialog"
>
<form @submit="handleSubmitContainer" class="flex flex-column gap-3">
<div class="flex flex-row flex-wrap justify-content-between align-items-center">
<label for="name" class="mr-8">{{ $t('c_productContainerOperations.Name') }}</label>
<div class="relative">
<InputText id="name" class="w-18rem" v-model="form.model.name.value.value"
type="text" v-bind="form.model.name.attr.value"/>
<error-span :error="form.context.errors.value.name"/>
</div>
</div>
<div class="flex flex-row flex-wrap justify-content-between align-items-center">
<label for="owner" class="mr-8">
{{ $t('c_POSCreate.Owner') }}
<i class="pi pi-exclamation-circle text-red-500 cursor-pointer"
v-tooltip.top="$t('tooltip.owner_revenue')"/>
</label>
<div class="flex flex-column flex-end relative">
<div v-if="state.create">
<Dropdown :placeholder="$t('c_POSCreate.Select owner')" :options="organsList" optionLabel="firstName"
v-model="form.model.owner.value.value" class="w-18rem" id="owner"
v-bind="form.model.owner.attr.value"/>
<error-span :error="form.context.errors.value.owner"/>
</div>
<div v-else-if="container">
<p class="my-0">{{ container.owner.firstName + ' ' + container.owner.lastName }}</p>
</div>
</div>
</div>
<div class="flex flex-row flex-wrap justify-content-between align-items-center">
<label for="name" class="mr-8">{{ $t('c_containerEditModal.Public') }}</label>
<div class="relative">
<Checkbox v-model="form.model.public.value.value" v-bind="form.model.public.attr.value"
inputId="publicContainer"
name="public" value="public" :binary="true"/>
<error-span :error="form.context.errors.value.public"/>
</div>
</div>
<div class="flex flex-row justify-content-end gap-2">
<Button outlined @click="closeDialog">{{ $t("c_containerEditModal.cancel") }}</Button>
<Button type="submit">{{ $t("c_containerEditModal.save") }}</Button>
</div>
</form>
<ContainerActionForm :form="form" :container="props.container"/>
<div class="flex flex-row justify-content-end gap-2 mt-3">
<Button outlined @click="closeDialog">{{ $t("c_containerEditModal.cancel") }}</Button>
<Button type="submit" @click="handleSubmitContainer">{{ $t("c_containerEditModal.save") }}</Button>
</div>
</Dialog>
</template>

<script setup lang="ts">
import { addListenerOnDialogueOverlay } from "@/utils/dialogUtil";
import Dialog from "primevue/dialog";
import { computed, type PropType, type Ref, ref } from "vue";
import { computed, type PropType, ref } from "vue";
import type {
BaseUserResponse, ContainerResponse, ContainerWithProductsResponse
} from "@sudosos/sudosos-client";
import { useAuthStore } from "@sudosos/sudosos-frontend-common";
import * as yup from "yup";
import Dropdown from "primevue/dropdown";
import Button from "primevue/button";
import ErrorSpan from "@/components/ErrorSpan.vue";
import { useContainerStore } from "@/stores/container.store";
import { handleError } from "@/utils/errorUtils";
import { useToast } from "primevue/usetoast";
import { useI18n } from "vue-i18n";
import InputText from "primevue/inputtext";
import { specToForm } from "@/utils/formUtil";
import { useAuthStore } from "@sudosos/sudosos-frontend-common";
import { storeToRefs } from "pinia";
import ContainerActionForm from "@/components/container/ContainerActionForm.vue";
const { t } = useI18n();
Expand All @@ -81,13 +44,10 @@ const props = defineProps({
});
const emit = defineEmits(['update:visible', 'create:container']);
const authStore = useAuthStore();
const containerStore = useContainerStore();
const visible = ref(false);
const dialog = ref();
const organsList: Ref<BaseUserResponse[]> = ref(authStore.organs);
const toast = useToast();
const state = computed(() => {
Expand All @@ -96,6 +56,7 @@ const state = computed(() => {
edit: props.container != undefined,
};
});
const header = computed(() => {
if (state.value.create) return t('c_containerEditModal.header.create');
if (state.value.edit) return t('c_containerEditModal.header.edit');
Expand Down Expand Up @@ -153,10 +114,11 @@ const handleSubmitContainer = form.context.handleSubmit(async (values) => {
closeDialog();
});
const { organs } = storeToRefs(useAuthStore());
const updateFieldValues = (p: ContainerWithProductsResponse) => {
if (!p) return;
const name = p.name;
const owner = organsList.value.find((o) => o.id == p.owner.id);
const owner = organs.value.find((o) => o.id == p.owner.id);
const isPublic = p.public;
form.context.resetForm();
form.context.setValues({ name, owner, public: isPublic });
Expand Down
5 changes: 3 additions & 2 deletions apps/dashboard/src/utils/formUtil.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import type { BaseFieldProps, FormContext, GenericObject, TypedSchema } from "ve
import { toTypedSchema } from "@vee-validate/yup";
import { useForm } from "vee-validate";

interface Form<T> {
export interface Form<T> {
context: FormContext
schema: TypedSchema
model: { [K in keyof T]: { value: Ref, attr: Ref<BaseFieldProps & GenericObject> } }
Expand Down Expand Up @@ -35,6 +35,7 @@ export function specToForm<T extends Record<string, yup.AnySchema>>(spec: T): Fo
return {
context,
schema,
model
model,
};
}

7 changes: 7 additions & 0 deletions apps/dashboard/src/utils/validation-schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import * as yup from "yup";
import { ref } from "vue";
import type { Ref } from "vue";
import i18n from './i18nUtils';
import type { BaseUserResponse } from "@sudosos/sudosos-client";

const t = i18n.global.t;

Expand Down Expand Up @@ -52,3 +53,9 @@ export const userTypes : Ref<Array<{name: string, value: number}>> = ref([
{ name: 'INVOICE', value: 6 },
{ name: 'AUTOMATIC_INVOICE', value: 7 },
]);

export const createContainerSpec = {
name: yup.string().required(),
public: yup.boolean().required().default(true),
owner: yup.mixed<BaseUserResponse>().required(),
};

0 comments on commit 6428a17

Please sign in to comment.