Refactor person creation workflow: Introduce PersonEdit component and integrate it across Create, Person.vue, and modals for improved modularity. Update type definitions and API methods for consistency.

This commit is contained in:
2025-09-12 23:51:52 +02:00
parent 062167d8a0
commit 49f7ecd54a
12 changed files with 692 additions and 624 deletions

View File

@@ -1,15 +1,35 @@
import {GenericDoc} from "ChillDocStoreAssets/types/generic_doc";
import {StoredObject, StoredObjectStatus} from "ChillDocStoreAssets/types";
import {CreatableEntityType} from "ChillPersonAssets/types";
import { GenericDoc } from "ChillDocStoreAssets/types/generic_doc";
import { StoredObject, StoredObjectStatus } from "ChillDocStoreAssets/types";
import { CreatableEntityType } from "ChillPersonAssets/types";
export interface DateTime {
datetime: string;
datetime8601: string;
}
/**
* A date representation to use when we create an instance
*/
export interface DateTimeCreate {
/**
* Must be a string in format Y-m-d\TH:i:sO
*/
datetime: string;
}
export interface Civility {
type: "chill_main_civility";
id: number;
// TODO
abbreviation: TranslatableString;
active: boolean;
name: TranslatableString;
}
export interface Gender {
type: "chill_main_gender";
id: number;
label: string;
genderTranslation: string;
}
export interface Household {
@@ -284,7 +304,7 @@ export interface addNewEntities {
* Configuration for the CreateModal and Create component
*/
export interface CreateComponentConfig {
action?: string;
allowedTypes: CreatableEntityType[];
query?: string;
action?: string;
allowedTypes: CreatableEntityType[];
query?: string;
}

View File

@@ -1,6 +1,6 @@
<template>
<ul class="nav nav-tabs">
<li v-if="allowedTypes.includes('person')" class="nav-item">
<li v-if="containsPerson" class="nav-item">
<a class="nav-link" :class="{ active: isActive('person') }">
<label for="person">
<input
@@ -14,7 +14,7 @@
</label>
</a>
</li>
<li v-if="allowedTypes.includes('thirdparty')" class="nav-item">
<li v-if="containsThirdParty" class="nav-item">
<a class="nav-link" :class="{ active: isActive('thirdparty') }">
<label for="thirdparty">
<input
@@ -31,9 +31,9 @@
</ul>
<div class="my-4">
<on-the-fly-person
<PersonEdit
v-if="type === 'person'"
:action="action"
action="create"
:query="query"
ref="castPerson"
/>
@@ -47,17 +47,26 @@
</div>
</template>
<script setup lang="ts">
import {computed, onMounted, ref} from "vue";
import { computed, onMounted, ref } from "vue";
import OnTheFlyPerson from "ChillPersonAssets/vuejs/_components/OnTheFly/Person.vue";
import OnTheFlyThirdparty from "ChillThirdPartyAssets/vuejs/_components/OnTheFly/ThirdParty.vue";
import {ONTHEFLY_CREATE_PERSON, ONTHEFLY_CREATE_THIRDPARTY, trans,} from "translator";
import {CreatableEntityType} from "ChillPersonAssets/types";
import {CreateComponentConfig} from "ChillMainAssets/types";
import {
ONTHEFLY_CREATE_PERSON,
ONTHEFLY_CREATE_THIRDPARTY,
trans,
} from "translator";
import { CreatableEntityType } from "ChillPersonAssets/types";
import { CreateComponentConfig } from "ChillMainAssets/types";
import PersonEdit from "ChillPersonAssets/vuejs/_components/OnTheFly/PersonEdit.vue";
const props = defineProps<CreateComponentConfig>();
const type = ref<CreatableEntityType| null>(null);
const props = withDefaults(defineProps<CreateComponentConfig>(), {
allowedTypes: ["person", "thirdparty"],
action: "create",
query: "",
});
const type = ref<CreatableEntityType | null>(null);
const radioType = computed<CreatableEntityType| null>({
const radioType = computed<CreatableEntityType | null>({
get: () => type.value,
set: (val: CreatableEntityType | null) => {
type.value = val;
@@ -65,7 +74,10 @@ const radioType = computed<CreatableEntityType| null>({
},
});
type AnyComponentInstance = InstanceType<typeof OnTheFlyPerson> | InstanceType<typeof OnTheFlyThirdparty> | null;
type AnyComponentInstance =
| InstanceType<typeof OnTheFlyPerson>
| InstanceType<typeof OnTheFlyThirdparty>
| null;
const castPerson = ref<AnyComponentInstance>(null);
const castThirdparty = ref<AnyComponentInstance>(null);
@@ -81,6 +93,14 @@ function isActive(tab: CreatableEntityType) {
return type.value === tab;
}
const containsThirdParty = computed<boolean>(() =>
props.allowedTypes.includes("thirdparty"),
);
const containsPerson = computed<boolean>(() => {
console.log(props.allowedTypes);
return props.allowedTypes.includes("person");
});
// Types for data structures coming from child components are not declared in TS yet.
// We conservatively type them as any to preserve runtime behavior while enabling TS in this component.
function castDataByType(): any {

View File

@@ -1,9 +1,12 @@
<script setup lang="ts">
import Modal from "ChillMainAssets/vuejs/_components/Modal.vue";
import Create from "ChillMainAssets/vuejs/OnTheFly/components/Create.vue";
import {CreateComponentConfig} from "ChillMainAssets/types";
import { CreateComponentConfig } from "ChillMainAssets/types";
const emit = defineEmits<(e: "close") => void>();
const props = defineProps<CreateComponentConfig>();
const modalDialogClass = { "modal-xl": true, "modal-scrollable": true };
</script>
<template>
@@ -18,15 +21,15 @@ const props = defineProps<CreateComponentConfig>();
</template>
<template #body-head>
<div class="modal-body">
<Create :allowed-types="props.allowed-types" :action="props.action" :query="props.query"></Create>
<Create
:allowedTypes="props.allowedTypes"
:action="props.action"
:query="props.query"
></Create>
</div>
</template>
</modal>
</teleport>
</modal>
</teleport>
</template>
<style scoped lang="scss">
</style>
<style scoped lang="scss"></style>

View File

@@ -76,7 +76,8 @@ import {
Entities,
EntitiesOrMe,
EntityType,
SearchOptions, Suggestion,
SearchOptions,
Suggestion,
} from "ChillPersonAssets/types";
import {
PICK_ENTITY_MODAL_TITLE,
@@ -183,7 +184,7 @@ function addNewSuggested(entity: EntitiesOrMe) {
emits("addNewEntity", { entity });
}
function addNewEntity({ selected }: { selected: Suggestion[]}) {
function addNewEntity({ selected }: { selected: Suggestion[] }) {
Object.values(selected).forEach((item) => {
emits("addNewEntity", { entity: item.result });
});

View File

@@ -52,23 +52,15 @@ import { trans, MODAL_ACTION_CLOSE } from "translator";
import { defineProps } from "vue";
export interface ModalProps {
modalDialogClass: string;
hideFooter: boolean;
modalDialogClass?: string | Record<string, boolean>;
hideFooter?: boolean;
show?: boolean;
}
defineProps({
modalDialogClass: {
type: String,
default: "",
},
hideFooter: {
type: Boolean,
default: false,
},
show: {
type: Boolean,
default: true,
},
const props = withDefaults(defineProps<ModalProps>(), {
modalDialogClass: "",
hideFooter: false,
show: true,
});
const emits = defineEmits<{