Files
CRM_Montzar/apps/web/src/components/notes/NoteCustomFields.vue
T
MahdiandCursor 8e1e94a439 feat(notes): let organizations define their own note fields
The note form was fixed. Owners can add fields and each note keeps those values.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-11-01 15:38:05 +03:30

129 lines
3.1 KiB
Vue

<script setup lang="ts">
import type { CustomFieldDefinitionDto } from '@mento/shared';
import JalaliDateInput from '@/components/JalaliDateInput.vue';
const props = defineProps<{
fields: CustomFieldDefinitionDto[];
modelValue: Record<string, unknown>;
}>();
const emit = defineEmits<{
'update:modelValue': [value: Record<string, unknown>];
}>();
function setValue(key: string, value: unknown) {
emit('update:modelValue', { ...props.modelValue, [key]: value });
}
function textValue(key: string) {
const value = props.modelValue[key];
if (value == null) return '';
return String(value);
}
function numberValue(key: string) {
const value = props.modelValue[key];
if (value == null || value === '') return '';
const n = Number(value);
return Number.isFinite(n) ? String(n) : '';
}
</script>
<template>
<div v-if="fields.length" class="note-custom-fields">
<p class="note-custom-title">فیلدهای اختصاصی</p>
<div v-for="field in fields" :key="field.id" class="field">
<span>
{{ field.label }}
<em v-if="field.required">*</em>
</span>
<select
v-if="field.fieldType === 'select'"
:value="textValue(field.key)"
@change="setValue(field.key, ($event.target as HTMLSelectElement).value)"
>
<option value="">انتخاب کنید</option>
<option v-for="opt in field.options" :key="opt" :value="opt">{{ opt }}</option>
</select>
<label v-else-if="field.fieldType === 'boolean'" class="check-line">
<input
type="checkbox"
:checked="props.modelValue[field.key] === true"
@change="setValue(field.key, ($event.target as HTMLInputElement).checked)"
/>
<span>بله</span>
</label>
<input
v-else-if="field.fieldType === 'number'"
type="number"
:value="numberValue(field.key)"
@input="
setValue(
field.key,
($event.target as HTMLInputElement).value === ''
? null
: Number(($event.target as HTMLInputElement).value),
)
"
/>
<JalaliDateInput
v-else-if="field.fieldType === 'date'"
:model-value="textValue(field.key)"
@update:model-value="setValue(field.key, $event || null)"
/>
<input
v-else
type="text"
:value="textValue(field.key)"
@input="setValue(field.key, ($event.target as HTMLInputElement).value)"
/>
</div>
</div>
</template>
<style scoped>
.note-custom-fields {
display: flex;
flex-direction: column;
gap: 0.55rem;
}
.note-custom-title {
margin: 0.2rem 0 0;
font-size: 0.82rem;
font-weight: 700;
color: #0f766e;
}
.field {
display: flex;
flex-direction: column;
gap: 0.3rem;
font-size: 0.82rem;
color: #64748b;
}
.field em {
color: #b91c1c;
font-style: normal;
}
.field select,
.field input[type='text'],
.field input[type='number'] {
border: 1px solid #e2e8f0;
border-radius: 10px;
padding: 0.45rem 0.55rem;
font-size: 0.9rem;
color: #0f172a;
background: #fff;
}
.check-line {
display: flex;
align-items: center;
gap: 0.4rem;
color: #0f172a;
}
</style>