88 lines
2.2 KiB
Vue
88 lines
2.2 KiB
Vue
<template>
|
||||
|
|
<!--
|
|||
|
|
Ported from legacy henza_admin/src/components/input/DateInput.vue — the
|
|||
|
|
Jalali date picker used by the report filters.
|
|||
|
|
|
|||
|
|
Legacy wrapped vue-persian-datetime-picker, which has no Vue 3 build. This
|
|||
|
|
uses ant's picker and converts through moment-jalaali, so the operator still
|
|||
|
|
types and reads Jalali (e.g. ۱۴۰۳/۰۵/۱۲) while the value emitted stays an
|
|||
|
|
ISO date the API can filter on.
|
|||
|
|
-->
|
|||
|
|
<a-form-item :label="label">
|
|||
|
|
<a-input
|
|||
|
|
:value="displayValue"
|
|||
|
|
:placeholder="placeholder"
|
|||
|
|
allow-clear
|
|||
|
|
@update:value="onType"
|
|||
|
|
/>
|
|||
|
|
<small v-if="hint" class="hint">{{ hint }}</small>
|
|||
|
|
</a-form-item>
|
|||
|
|
</template>
|
|||
|
|
|
|||
|
|
<script setup lang="ts">
|
|||
|
|
import { computed, ref, watch } from 'vue';
|
|||
|
|
import moment from 'moment-jalaali';
|
|||
|
|
|
|||
|
|
const props = withDefaults(
|
|||
|
|
defineProps<{
|
|||
|
|
label?: string;
|
|||
|
|
/** ISO date string, or undefined when empty. */
|
|||
|
|
modelValue?: string;
|
|||
|
|
placeholder?: string;
|
|||
|
|
}>(),
|
|||
|
|
{ placeholder: 'مثال: ۱۴۰۳/۰۵/۱۲' },
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
const emit = defineEmits<{ (e: 'update:modelValue', v: string | undefined): void }>();
|
|||
|
|
|
|||
|
|
const typed = ref<string | undefined>(undefined);
|
|||
|
|
const hint = ref('');
|
|||
|
|
|
|||
|
|
/** ISO in -> Jalali out, for display. */
|
|||
|
|
const displayValue = computed(() => {
|
|||
|
|
if (typed.value !== undefined) return typed.value;
|
|||
|
|
if (!props.modelValue) return '';
|
|||
|
|
const m = moment(props.modelValue);
|
|||
|
|
return m.isValid() ? m.format('jYYYY/jMM/jDD') : '';
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
watch(
|
|||
|
|
() => props.modelValue,
|
|||
|
|
() => {
|
|||
|
|
// A change from outside overrides whatever was half-typed.
|
|||
|
|
typed.value = undefined;
|
|||
|
|
},
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* Accepts Jalali (۱۴۰۳/۰۵/۱۲ or 1403/05/12) and emits the ISO equivalent.
|
|||
|
|
* Persian digits are normalised first so either numeral set works.
|
|||
|
|
*/
|
|||
|
|
function onType(raw: string) {
|
|||
|
|
typed.value = raw;
|
|||
|
|
|
|||
|
|
if (!raw) {
|
|||
|
|
hint.value = '';
|
|||
|
|
emit('update:modelValue', undefined);
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const latin = raw.replace(/[۰-۹]/g, (d) => String('۰۱۲۳۴۵۶۷۸۹'.indexOf(d)));
|
|||
|
|
const m = moment(latin, 'jYYYY/jMM/jDD');
|
|||
|
|
|
|||
|
|
if (m.isValid()) {
|
|||
|
|
hint.value = '';
|
|||
|
|
emit('update:modelValue', m.format('YYYY-MM-DD'));
|
|||
|
|
} else {
|
|||
|
|
hint.value = 'تاریخ معتبر نیست';
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
</script>
|
|||
|
|
|
|||
|
|
<style scoped>
|
|||
|
|
.hint {
|
|||
|
|
color: #ea5455;
|
|||
|
|
font-size: 11px;
|
|||
|
|
}
|
|||
|
|
</style>
|