Teren-app/resources/js/Pages/Imports/Partials/TemplateControls.vue
Simon Pocrnjič dea7432deb changes
2025-12-26 22:39:58 +01:00

167 lines
5.8 KiB
Vue

<script setup>
import { computed } from "vue";
import { Select, SelectContent, SelectGroup, SelectItem, SelectTrigger, SelectValue } from "@/Components/ui/select";
import { Button } from "@/Components/ui/button";
import { Label } from "@/Components/ui/label";
import { Input } from "@/Components/ui/input";
import { Badge } from "@/Components/ui/badge";
const props = defineProps({
isCompleted: Boolean,
hasHeader: Boolean,
delimiterState: Object,
selectedTemplateOption: Object,
filteredTemplates: Array,
templateApplied: Boolean,
form: Object, // reactive object reference from parent
});
const emits = defineEmits([
"update:hasHeader",
"update:delimiterMode",
"update:delimiterCustom",
"apply-template",
"preview",
]);
function onHeaderChange(val) {
emits("update:hasHeader", val === "true");
}
function onDelimiterMode(val) {
emits("update:delimiterMode", val);
}
function onDelimiterCustom(e) {
emits("update:delimiterCustom", e.target.value);
}
// Proxy selected template object <-> form.import_template_id (which stores the id)
const selectedTemplateProxy = computed({
get() {
return props.selectedTemplateOption || null;
},
set(opt) {
props.form.import_template_id = opt ? opt.id : null;
},
});
</script>
<template>
<div class="space-y-4">
<div class="flex items-start justify-between gap-4">
<div class="flex-1">
<Label class="text-sm font-medium">Template</Label>
<Select
:model-value="selectedTemplateProxy?.id?.toString()"
@update:model-value="(val) => {
const tpl = filteredTemplates.find(t => t.id.toString() === val);
selectedTemplateProxy = tpl || null;
}"
>
<SelectTrigger class="mt-1">
<SelectValue placeholder="Izberi predlogo...">
<div v-if="selectedTemplateProxy" class="flex items-center gap-2">
<span>{{ selectedTemplateProxy.name }}</span>
<span v-if="selectedTemplateProxy.source_type" class="text-xs text-muted-foreground">({{ selectedTemplateProxy.source_type }})</span>
<Badge variant="outline" class="text-[10px]">{{ selectedTemplateProxy.client_id ? 'Client' : 'Global' }}</Badge>
</div>
</SelectValue>
</SelectTrigger>
<SelectContent>
<SelectGroup>
<SelectItem v-for="option in filteredTemplates" :key="option.id" :value="option.id.toString()">
<div class="flex items-center justify-between w-full gap-3">
<div class="flex items-center gap-2">
<span>{{ option.name }}</span>
<span v-if="option.source_type" class="text-xs text-muted-foreground">({{ option.source_type }})</span>
</div>
<Badge variant="outline" class="text-[10px]">{{
option.client_id ? "Client" : "Global"
}}</Badge>
</div>
</SelectItem>
</SelectGroup>
</SelectContent>
</Select>
<div v-if="isCompleted" class="mt-2">
<Button
variant="default"
size="sm"
class="w-full sm:w-auto"
@click="$emit('preview')"
>
Ogled CSV
</Button>
</div>
</div>
</div>
<div v-if="!isCompleted" class="flex flex-col gap-3">
<div class="flex flex-col sm:flex-row gap-3">
<div class="flex-1">
<Label class="text-xs font-medium">Header row</Label>
<Select
:model-value="hasHeader.toString()"
@update:model-value="onHeaderChange"
>
<SelectTrigger class="mt-1">
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectGroup>
<SelectItem value="true">Has header</SelectItem>
<SelectItem value="false">No header (positional)</SelectItem>
</SelectGroup>
</SelectContent>
</Select>
</div>
<div class="flex-1">
<Label class="text-xs font-medium">Delimiter</Label>
<Select
:model-value="delimiterState.mode"
@update:model-value="onDelimiterMode"
>
<SelectTrigger class="mt-1">
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectGroup>
<SelectItem value="auto">Auto-detect</SelectItem>
<SelectItem value="comma">Comma ,</SelectItem>
<SelectItem value="semicolon">Semicolon ;</SelectItem>
<SelectItem value="tab">Tab \t</SelectItem>
<SelectItem value="pipe">Pipe |</SelectItem>
<SelectItem value="space">Space ␠</SelectItem>
<SelectItem value="custom">Custom…</SelectItem>
</SelectGroup>
</SelectContent>
</Select>
</div>
</div>
<div v-if="delimiterState.mode === 'custom'" class="flex items-end gap-3">
<div class="w-40">
<Label class="text-xs font-medium">Custom delimiter</Label>
<Input
:model-value="delimiterState.custom"
@input="onDelimiterCustom"
maxlength="4"
placeholder=","
class="mt-1"
/>
</div>
<p class="text-xs text-muted-foreground">
Template default: {{ selectedTemplateOption?.meta?.delimiter || "auto" }}
</p>
</div>
<p v-else class="text-xs text-muted-foreground">
Template default: {{ selectedTemplateOption?.meta?.delimiter || "auto" }}
</p>
</div>
<Button
v-if="!isCompleted && form.import_template_id"
variant="default"
@click="$emit('apply-template')"
class="w-full"
>
{{ templateApplied ? 'Re-apply Template' : 'Apply Template' }}
</Button>
</div>
</template>