add business category
This commit is contained in:
@@ -20,7 +20,7 @@
|
||||
<div class="min-w-0">
|
||||
<p class="font-medium text-text">{{ svc.serviceTemplate?.title ?? 'خدمت' }}</p>
|
||||
<p class="text-xs text-muted">
|
||||
{{ formatPrice(svc.price) }} تومان
|
||||
{{ formatPriceToman(svc.price) }} تومان
|
||||
<span v-if="svc.durationMinutes"> · {{ svc.durationMinutes }} دقیقه</span>
|
||||
</p>
|
||||
</div>
|
||||
@@ -45,13 +45,10 @@
|
||||
label="نوع خدمت"
|
||||
:options="templateOptions"
|
||||
/>
|
||||
<AppInput
|
||||
<PriceInput
|
||||
id="svcPrice"
|
||||
v-model="form.price"
|
||||
label="قیمت (تومان)"
|
||||
type="number"
|
||||
inputmode="numeric"
|
||||
ltr
|
||||
required
|
||||
/>
|
||||
<AppButton type="submit" class="sm:col-span-2" :loading="adding">
|
||||
@@ -79,8 +76,9 @@ import { fetchServiceTemplates } from '@/api/service-templates';
|
||||
import type { ServiceTemplate } from '@/api/types';
|
||||
import { ApiError } from '@/api/client';
|
||||
import AppButton from '@/components/ui/AppButton.vue';
|
||||
import AppInput from '@/components/ui/AppInput.vue';
|
||||
import AppSelect from '@/components/ui/AppSelect.vue';
|
||||
import PriceInput from '@/components/ui/PriceInput.vue';
|
||||
import { formatPriceToman, parsePriceInput } from '@/utils/price';
|
||||
|
||||
const props = defineProps<{
|
||||
businessId: string;
|
||||
@@ -104,12 +102,6 @@ const templateOptions = computed(() =>
|
||||
availableTemplates.value.map((t) => ({ value: t.id, label: t.title })),
|
||||
);
|
||||
|
||||
function formatPrice(price: string): string {
|
||||
const n = Number.parseFloat(price);
|
||||
if (!Number.isFinite(n)) return price;
|
||||
return new Intl.NumberFormat('fa-IR').format(Math.round(n));
|
||||
}
|
||||
|
||||
async function load() {
|
||||
loading.value = true;
|
||||
error.value = '';
|
||||
@@ -130,17 +122,8 @@ async function load() {
|
||||
}
|
||||
}
|
||||
|
||||
function parsePrice(value: string | number): number | null {
|
||||
if (value === '' || value == null) return null;
|
||||
if (typeof value === 'number') {
|
||||
return Number.isFinite(value) && value >= 0 ? value : null;
|
||||
}
|
||||
const n = Number.parseFloat(String(value).replace(/,/g, '').trim());
|
||||
return Number.isFinite(n) && n >= 0 ? n : null;
|
||||
}
|
||||
|
||||
async function onAdd() {
|
||||
const price = parsePrice(form.value.price);
|
||||
const price = parsePriceInput(form.value.price);
|
||||
if (!form.value.serviceTemplateId || price === null) {
|
||||
error.value = 'نوع خدمت و قیمت معتبر را وارد کنید.';
|
||||
return;
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
<template>
|
||||
<div class="space-y-1.5">
|
||||
<label v-if="label" :for="id" class="block text-sm font-medium text-muted">
|
||||
{{ label }}
|
||||
</label>
|
||||
<input
|
||||
:id="id"
|
||||
:value="display"
|
||||
type="text"
|
||||
inputmode="numeric"
|
||||
class="w-full rounded-xl border border-border bg-surface-2 px-4 py-3 text-text outline-none transition placeholder:text-muted focus:border-brand-500 focus:ring-2 focus:ring-brand-500/30"
|
||||
:class="ltr ? 'text-left' : ''"
|
||||
:placeholder="placeholder"
|
||||
:required="required"
|
||||
:disabled="disabled"
|
||||
dir="ltr"
|
||||
@input="onInput"
|
||||
@blur="onBlur"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, watch } from 'vue';
|
||||
import { digitsOnlyPrice, formatPriceInputDisplay } from '@/utils/price';
|
||||
|
||||
const model = defineModel<string>({ default: '' });
|
||||
|
||||
withDefaults(
|
||||
defineProps<{
|
||||
label?: string;
|
||||
id?: string;
|
||||
ltr?: boolean;
|
||||
placeholder?: string;
|
||||
required?: boolean;
|
||||
disabled?: boolean;
|
||||
}>(),
|
||||
{ ltr: true, placeholder: '۰', required: false, disabled: false },
|
||||
);
|
||||
|
||||
const display = ref(formatPriceInputDisplay(model.value));
|
||||
|
||||
watch(
|
||||
() => model.value,
|
||||
(v) => {
|
||||
const next = formatPriceInputDisplay(v);
|
||||
if (next !== display.value) display.value = next;
|
||||
},
|
||||
);
|
||||
|
||||
function onInput(e: Event) {
|
||||
const raw = (e.target as HTMLInputElement).value;
|
||||
const digits = digitsOnlyPrice(raw);
|
||||
model.value = digits;
|
||||
display.value = digits ? formatPriceInputDisplay(digits) : '';
|
||||
}
|
||||
|
||||
function onBlur() {
|
||||
display.value = formatPriceInputDisplay(model.value);
|
||||
}
|
||||
</script>
|
||||
Reference in New Issue
Block a user