1<template>
2 <div class="flex justify-between items-start flex-col gap-6">
3 <span class="text-sm text-ink-gray-5 pt-4 w-full"
4 >Set visibility and mandatory criteria for
5 {{ selections.childField || "child" }} field:</span
6 >
7 <div class="flex flex-col gap-4 w-full pb-2">
8 <!-- Display Criteria -->
9 <div class="flex items-center gap-3 justify-between">
10 <div class="flex gap-3 items-center">
11 <Switch v-model="fieldCriteriaState.display.enabled" />
12 <div class="flex items-center gap-1">
13 <span class="text-sm text-ink-gray-5"
14 >Show {{ selections.childField }} if
15 {{ selections.parentField }} is set to</span
16 >
17 <DocumentationButton
18 url="https://github.com/ikhsanddy/opendesk"
19 color="!text-ink-gray-6"
20 />
21 </div>
22 </div>
23 <MultiSelect
24 class="min-w-[120px] max-w-[120px]"
25 side="top"
26 :disabled="!fieldCriteriaState.display.enabled"
27 :options="fieldCriteriaOptions"
28 :model-value="selectedValues('display')"
29 :placeholder="__('Select Child Field values')"
30 @update:model-value="handleCriteriaSelection($event, 'display')"
31 />
32 </div>
33 <!-- Mandatory Criteria -->
34 <div class="flex items-center gap-3 justify-between w-full">
35 <div class="flex gap-3 items-center">
36 <Switch v-model="fieldCriteriaState.mandatory.enabled" />
37 <div class="flex items-center gap-1">
38 <span class="text-sm text-ink-gray-5"
39 >Make {{ selections.childField }} mandatory if
40 {{ selections.parentField }} is set to</span
41 >
42 <DocumentationButton
43 url="https://github.com/ikhsanddy/opendesk"
44 color="!text-ink-gray-6"
45 />
46 </div>
47 </div>
48 <MultiSelect
49 class="min-w-[120px] max-w-[120px]"
50 side="top"
51 :disabled="!fieldCriteriaState.mandatory.enabled"
52 :options="fieldCriteriaOptions"
53 :model-value="selectedValues('mandatory')"
54 :placeholder="__('Select Child Field values')"
55 @update:model-value="handleCriteriaSelection($event, 'mandatory')"
56 />
57 </div>
58 </div>
59 </div>
60</template>
61
62<script setup lang="ts">
63import DocumentationButton from "@/components/DocumentationButton.vue";
64import { getMeta } from "@/stores/meta";
65import { __ } from "@/translation";
66import { MultiSelect, Switch } from "frappe-ui";
67import { computed } from "vue";
68
69const props = defineProps<{
70 parentFieldValues: string[];
71}>();
72
73const fieldCriteriaState = defineModel<{
74 display: { enabled: boolean; value: Record<"label" | "value", string>[] };
75 mandatory: { enabled: boolean; value: Record<"label" | "value", string>[] };
76}>();
77const state = defineModel("selections") as any;
78
79const { getField } = getMeta("OD Ticket");
80
81const selections = computed(() => {
82 let childField = state.value.selectedChildField;
83 let parentField = state.value.selectedParentField;
84 childField = getField(childField)?.label;
85 parentField = getField(parentField)?.label;
86 return { childField, parentField };
87});
88
89const fieldCriteriaOptions = computed(() => {
90 const _options = [{ label: "Any", value: "Any" }];
91 props.parentFieldValues.forEach((value) => {
92 if (!_options.some((o) => o.value === value)) {
93 _options.push({ label: value, value });
94 }
95 });
96 return _options;
97});
98
99function selectedValues(stateKey: "display" | "mandatory") {
100 return fieldCriteriaState.value[stateKey].value.map((v) => v.value);
101}
102
103function handleCriteriaSelection(
104 values: string[],
105 stateKey: "display" | "mandatory"
106) {
107 // "Any" is exclusive: picking it drops the rest, picking anything else drops it
108 const wasAnySelected = selectedValues(stateKey).includes("Any");
109 let selected =
110 values.includes("Any") && !wasAnySelected
111 ? ["Any"]
112 : values.filter((value) => value !== "Any");
113 if (!selected.length) selected = ["Any"];
114 fieldCriteriaState.value[stateKey].value = selected.map((value) => ({
115 label: value,
116 value,
117 }));
118}
119</script>
120
121<style scoped></style>
122