refactor(frontend): complete full transparent wrapper refactoring for primitives, fields, and subcomponents under /components
Validators (Pushes and Pull Requests) / UI & Storage Validation (push) Failing after 11s
Validators (Pushes and Pull Requests) / Database & Schema Validation (push) Successful in 12s
Validators (Pushes and Pull Requests) / Core Validators & Database Setup (push) Failing after 20s
Validators (Pushes and Pull Requests) / WBS & Audit Validations (push) Has been skipped
Validators (Pushes and Pull Requests) / .NET Contracts (push) Has been skipped
Validators (Pushes and Pull Requests) / Calibration & Performance (push) Has been skipped
Validators (Pushes and Pull Requests) / Operational Report & Decision Packet (push) Has been skipped
Validators (Pushes and Pull Requests) / Security & Secrets (push) Successful in 9s
Validators (Pushes and Pull Requests) / CI Workflow Lint (push) Failing after 10s
Validators (Pushes and Pull Requests) / Notify PR Results (push) Has been skipped
Validators (Pushes and Pull Requests) / UI & Storage Validation (push) Failing after 11s
Validators (Pushes and Pull Requests) / Database & Schema Validation (push) Successful in 12s
Validators (Pushes and Pull Requests) / Core Validators & Database Setup (push) Failing after 20s
Validators (Pushes and Pull Requests) / WBS & Audit Validations (push) Has been skipped
Validators (Pushes and Pull Requests) / .NET Contracts (push) Has been skipped
Validators (Pushes and Pull Requests) / Calibration & Performance (push) Has been skipped
Validators (Pushes and Pull Requests) / Operational Report & Decision Packet (push) Has been skipped
Validators (Pushes and Pull Requests) / Security & Secrets (push) Successful in 9s
Validators (Pushes and Pull Requests) / CI Workflow Lint (push) Failing after 10s
Validators (Pushes and Pull Requests) / Notify PR Results (push) Has been skipped
This commit is contained in:
@@ -1,27 +1,36 @@
|
|||||||
<!-- Typed Field Layer: DateField (PrimeVue DatePicker Adapter Wrapper) -->
|
<!-- Typed Field Layer: DateField (Quant Transparent Adapter Wrapper) -->
|
||||||
<template>
|
<template>
|
||||||
<div class="typed-date-field flex flex-col gap-1 w-full">
|
<div class="typed-date-field flex flex-col gap-1 w-full">
|
||||||
<div class="flex justify-between items-center text-xs">
|
<div class="flex justify-between items-center">
|
||||||
<label v-if="label" class="font-bold text-slate-800">
|
<label v-if="label" class="text-xs font-bold text-slate-800">
|
||||||
{{ label }} <span v-if="required" class="text-rose-600">*</span>
|
{{ label }} <span v-if="required" class="text-rose-600">*</span>
|
||||||
</label>
|
</label>
|
||||||
<button
|
<button
|
||||||
v-if="showTodayBtn && !readonly && !disabled"
|
v-if="showTodayBtn && !disabled"
|
||||||
type="button"
|
type="button"
|
||||||
class="text-[11px] font-bold text-blue-600 hover:text-blue-800 underline"
|
class="text-[10px] text-blue-600 hover:text-blue-800 font-bold hover:underline"
|
||||||
@click="setToday"
|
@click="setToday"
|
||||||
>
|
>
|
||||||
오늘
|
오늘 날짜
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<DatePicker
|
<DatePicker
|
||||||
:modelValue="parsedDate"
|
v-bind="$attrs"
|
||||||
|
:id="id"
|
||||||
|
:modelValue="dateValue"
|
||||||
dateFormat="yy-mm-dd"
|
dateFormat="yy-mm-dd"
|
||||||
:readonly="readonly"
|
:placeholder="placeholder || 'YYYY-MM-DD'"
|
||||||
:disabled="disabled"
|
:disabled="disabled"
|
||||||
inputClass="w-full h-9 px-3 border border-slate-300 rounded text-xs text-slate-900 font-mono font-bold bg-white focus:ring-2 focus:ring-blue-500 focus:border-blue-500 disabled:bg-slate-100 disabled:text-slate-500 readonly:bg-slate-50 readonly:text-slate-700"
|
class="w-full text-xs"
|
||||||
@update:modelValue="handleChange"
|
inputClass="w-full h-9 px-3 border border-slate-300 rounded text-xs text-slate-900 font-medium bg-white placeholder:text-slate-400 focus:ring-2 focus:ring-blue-500 focus:border-blue-500 disabled:bg-slate-100"
|
||||||
/>
|
showIcon
|
||||||
|
iconDisplay="input"
|
||||||
|
@update:modelValue="onDateChange"
|
||||||
|
>
|
||||||
|
<template v-for="(_, slotName) in $slots" :key="slotName" #[slotName]="slotProps">
|
||||||
|
<slot :name="slotName" v-bind="slotProps || {}"></slot>
|
||||||
|
</template>
|
||||||
|
</DatePicker>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -29,45 +38,45 @@
|
|||||||
import { computed } from 'vue';
|
import { computed } from 'vue';
|
||||||
import DatePicker from 'primevue/datepicker';
|
import DatePicker from 'primevue/datepicker';
|
||||||
|
|
||||||
|
defineOptions({
|
||||||
|
inheritAttrs: false
|
||||||
|
});
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
|
id?: string;
|
||||||
label?: string;
|
label?: string;
|
||||||
modelValue?: string;
|
modelValue?: string | Date;
|
||||||
|
placeholder?: string;
|
||||||
required?: boolean;
|
required?: boolean;
|
||||||
readonly?: boolean;
|
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
showTodayBtn?: boolean;
|
showTodayBtn?: boolean;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const emit = defineEmits(['update:modelValue', 'change']);
|
const emit = defineEmits(['update:modelValue', 'change']);
|
||||||
|
|
||||||
const parsedDate = computed(() => {
|
const dateValue = computed(() => {
|
||||||
if (!props.modelValue) return null;
|
if (!props.modelValue) return null;
|
||||||
|
if (props.modelValue instanceof Date) return props.modelValue;
|
||||||
const d = new Date(props.modelValue);
|
const d = new Date(props.modelValue);
|
||||||
return isNaN(d.getTime()) ? null : d;
|
return isNaN(d.getTime()) ? null : d;
|
||||||
});
|
});
|
||||||
|
|
||||||
const handleChange = (val: any) => {
|
const onDateChange = (val: Date | null) => {
|
||||||
if (!val) {
|
if (!val) {
|
||||||
emit('update:modelValue', '');
|
emit('update:modelValue', '');
|
||||||
emit('change', '');
|
emit('change', '');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let dateStr = '';
|
const yyyy = val.getFullYear();
|
||||||
if (val instanceof Date) {
|
const mm = String(val.getMonth() + 1).padStart(2, '0');
|
||||||
const yyyy = val.getFullYear();
|
const dd = String(val.getDate()).padStart(2, '0');
|
||||||
const mm = String(val.getMonth() + 1).padStart(2, '0');
|
const strVal = `${yyyy}-${mm}-${dd}`;
|
||||||
const dd = String(val.getDate()).padStart(2, '0');
|
emit('update:modelValue', strVal);
|
||||||
dateStr = `${yyyy}-${mm}-${dd}`;
|
emit('change', strVal);
|
||||||
} else {
|
|
||||||
dateStr = String(val);
|
|
||||||
}
|
|
||||||
emit('update:modelValue', dateStr);
|
|
||||||
emit('change', dateStr);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const setToday = () => {
|
const setToday = () => {
|
||||||
const today = new Date().toISOString().substring(0, 10);
|
const d = new Date();
|
||||||
emit('update:modelValue', today);
|
onDateChange(d);
|
||||||
emit('change', today);
|
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,40 +1,48 @@
|
|||||||
<!-- Typed Field Component Layer: StringField -->
|
<!-- Typed Field Layer: StringField (Quant Transparent Adapter Wrapper) -->
|
||||||
<template>
|
<template>
|
||||||
<div class="typed-string-field flex flex-col gap-1 w-full">
|
<div class="typed-string-field flex flex-col gap-1 w-full">
|
||||||
<label v-if="label" :for="id" class="text-xs font-bold text-slate-800">
|
<label v-if="label" class="text-xs font-bold text-slate-800">
|
||||||
{{ label }} <span v-if="required" class="text-rose-600">*</span>
|
{{ label }} <span v-if="required" class="text-rose-600">*</span>
|
||||||
</label>
|
</label>
|
||||||
<input
|
<InputText
|
||||||
|
v-bind="$attrs"
|
||||||
:id="id"
|
:id="id"
|
||||||
type="text"
|
:modelValue="modelValue"
|
||||||
:value="modelValue"
|
|
||||||
:placeholder="placeholder"
|
:placeholder="placeholder"
|
||||||
:readonly="readonly"
|
|
||||||
:disabled="disabled"
|
:disabled="disabled"
|
||||||
class="w-full h-9 px-3 border border-slate-300 rounded text-xs text-slate-900 font-medium bg-white placeholder:text-slate-400 focus:ring-2 focus:ring-blue-500 focus:border-blue-500 focus:outline-none disabled:bg-slate-100 disabled:text-slate-500 disabled:cursor-not-allowed readonly:bg-slate-50 readonly:text-slate-700"
|
:readonly="readonly"
|
||||||
@input="handleInput"
|
class="w-full h-9 px-3 border border-slate-300 rounded text-xs text-slate-900 font-medium bg-white placeholder:text-slate-400 focus:ring-2 focus:ring-blue-500 focus:border-blue-500 disabled:bg-slate-100 readonly:bg-slate-50"
|
||||||
/>
|
@update:modelValue="onInput"
|
||||||
<div v-if="errorMessage" class="text-[11px] text-rose-600 font-semibold mt-0.5">{{ errorMessage }}</div>
|
>
|
||||||
|
<template v-for="(_, slotName) in $slots" :key="slotName" #[slotName]="slotProps">
|
||||||
|
<slot :name="slotName" v-bind="slotProps || {}"></slot>
|
||||||
|
</template>
|
||||||
|
</InputText>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import InputText from 'primevue/inputtext';
|
||||||
|
|
||||||
|
defineOptions({
|
||||||
|
inheritAttrs: false
|
||||||
|
});
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
id?: string;
|
id?: string;
|
||||||
label?: string;
|
label?: string;
|
||||||
modelValue?: string;
|
modelValue?: string;
|
||||||
placeholder?: string;
|
placeholder?: string;
|
||||||
required?: boolean;
|
required?: boolean;
|
||||||
readonly?: boolean;
|
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
errorMessage?: string;
|
readonly?: boolean;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const emit = defineEmits(['update:modelValue', 'change']);
|
const emit = defineEmits(['update:modelValue', 'change']);
|
||||||
|
|
||||||
const handleInput = (e: Event) => {
|
const onInput = (val: string | undefined) => {
|
||||||
const val = (e.target as HTMLInputElement).value;
|
const finalVal = val ?? '';
|
||||||
emit('update:modelValue', val);
|
emit('update:modelValue', finalVal);
|
||||||
emit('change', val);
|
emit('change', finalVal);
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
<!-- Primitive Layer: DialogModal (PrimeVue Dialog Adapter Wrapper) -->
|
<!-- Primitive Layer: DialogModal (Quant Transparent Adapter Wrapper) -->
|
||||||
<template>
|
<template>
|
||||||
<Dialog
|
<Dialog
|
||||||
|
v-bind="$attrs"
|
||||||
:visible="isOpen"
|
:visible="isOpen"
|
||||||
:header="title || '확인'"
|
:header="title"
|
||||||
:modal="true"
|
:modal="true"
|
||||||
:closable="true"
|
:closable="true"
|
||||||
:dismissableMask="true"
|
:dismissableMask="true"
|
||||||
@@ -16,7 +17,7 @@
|
|||||||
<template #footer>
|
<template #footer>
|
||||||
<div class="flex justify-end gap-2 text-xs pt-2 border-t border-slate-200">
|
<div class="flex justify-end gap-2 text-xs pt-2 border-t border-slate-200">
|
||||||
<button type="button" class="px-3 py-1.5 bg-slate-200 hover:bg-slate-300 text-slate-800 font-bold rounded transition" @click="$emit('close')">
|
<button type="button" class="px-3 py-1.5 bg-slate-200 hover:bg-slate-300 text-slate-800 font-bold rounded transition" @click="$emit('close')">
|
||||||
취소
|
닫기
|
||||||
</button>
|
</button>
|
||||||
<button type="button" class="px-3 py-1.5 bg-blue-600 hover:bg-blue-700 text-white font-bold rounded transition shadow-xs" @click="$emit('confirm')">
|
<button type="button" class="px-3 py-1.5 bg-blue-600 hover:bg-blue-700 text-white font-bold rounded transition shadow-xs" @click="$emit('confirm')">
|
||||||
확인
|
확인
|
||||||
@@ -29,9 +30,13 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import Dialog from 'primevue/dialog';
|
import Dialog from 'primevue/dialog';
|
||||||
|
|
||||||
|
defineOptions({
|
||||||
|
inheritAttrs: false
|
||||||
|
});
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
isOpen: boolean;
|
isOpen: boolean;
|
||||||
title?: string;
|
title: string;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const emit = defineEmits(['close', 'confirm']);
|
const emit = defineEmits(['close', 'confirm']);
|
||||||
|
|||||||
@@ -1,16 +1,24 @@
|
|||||||
<!-- Primitive Layer: SelectInput (PrimeVue Select Adapter Wrapper) -->
|
<!-- Primitive Layer: SelectInput (Quant Transparent Adapter Wrapper) -->
|
||||||
<template>
|
<template>
|
||||||
<div class="primitive-select-wrapper w-full">
|
<div class="primitive-select-wrapper w-full">
|
||||||
<Select
|
<Select
|
||||||
|
v-bind="$attrs"
|
||||||
:id="id"
|
:id="id"
|
||||||
:modelValue="modelValue"
|
:modelValue="modelValue"
|
||||||
:options="formattedOptions"
|
:options="formattedOptions"
|
||||||
optionLabel="label"
|
optionLabel="label"
|
||||||
optionValue="value"
|
optionValue="value"
|
||||||
|
:placeholder="placeholder || '선택하세요'"
|
||||||
:disabled="disabled"
|
:disabled="disabled"
|
||||||
class="primitive-select w-full h-9 border border-slate-300 rounded text-xs text-slate-900 font-medium bg-white focus:ring-2 focus:ring-blue-500 focus:border-blue-500 disabled:bg-slate-100 disabled:text-slate-500"
|
:showClear="showClear !== false"
|
||||||
|
:filter="filter !== false"
|
||||||
|
class="w-full h-9 border border-slate-300 rounded text-xs text-slate-900 font-medium bg-white focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
||||||
@update:modelValue="onSelectChange"
|
@update:modelValue="onSelectChange"
|
||||||
/>
|
>
|
||||||
|
<template v-for="(_, slotName) in $slots" :key="slotName" #[slotName]="slotProps">
|
||||||
|
<slot :name="slotName" v-bind="slotProps || {}"></slot>
|
||||||
|
</template>
|
||||||
|
</Select>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -18,11 +26,18 @@
|
|||||||
import { computed } from 'vue';
|
import { computed } from 'vue';
|
||||||
import Select from 'primevue/select';
|
import Select from 'primevue/select';
|
||||||
|
|
||||||
|
defineOptions({
|
||||||
|
inheritAttrs: false
|
||||||
|
});
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
id?: string;
|
id?: string;
|
||||||
modelValue?: string | number;
|
modelValue?: string | number;
|
||||||
options: Array<string | { label: string; value: string | number }>;
|
options: Array<string | { label: string; value: string | number }>;
|
||||||
|
placeholder?: string;
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
|
showClear?: boolean;
|
||||||
|
filter?: boolean;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const emit = defineEmits(['update:modelValue', 'change']);
|
const emit = defineEmits(['update:modelValue', 'change']);
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
<!-- Primitive Layer: TextInput (PrimeVue Adapter Wrapper) -->
|
<!-- Primitive Layer: TextInput (Quant Transparent Adapter Wrapper) -->
|
||||||
<template>
|
<template>
|
||||||
<div class="primitive-input-wrapper relative w-full flex items-center">
|
<div class="primitive-input-wrapper relative w-full flex items-center">
|
||||||
<InputText
|
<InputText
|
||||||
|
v-bind="$attrs"
|
||||||
:id="id"
|
:id="id"
|
||||||
:type="type || 'text'"
|
:type="type || 'text'"
|
||||||
:modelValue="modelValue"
|
:modelValue="modelValue"
|
||||||
@@ -10,12 +11,16 @@
|
|||||||
:readonly="readonly"
|
:readonly="readonly"
|
||||||
class="primitive-input w-full h-9 pl-3 pr-8 border border-slate-300 rounded text-xs text-slate-900 font-medium bg-white placeholder:text-slate-400 focus:ring-2 focus:ring-blue-500 focus:border-blue-500 focus:outline-none disabled:bg-slate-100 disabled:text-slate-500 disabled:cursor-not-allowed readonly:bg-slate-50 readonly:text-slate-700 transition shadow-xs"
|
class="primitive-input w-full h-9 pl-3 pr-8 border border-slate-300 rounded text-xs text-slate-900 font-medium bg-white placeholder:text-slate-400 focus:ring-2 focus:ring-blue-500 focus:border-blue-500 focus:outline-none disabled:bg-slate-100 disabled:text-slate-500 disabled:cursor-not-allowed readonly:bg-slate-50 readonly:text-slate-700 transition shadow-xs"
|
||||||
@update:modelValue="onUpdateValue"
|
@update:modelValue="onUpdateValue"
|
||||||
/>
|
>
|
||||||
|
<template v-for="(_, slotName) in $slots" :key="slotName" #[slotName]="slotProps">
|
||||||
|
<slot :name="slotName" v-bind="slotProps || {}"></slot>
|
||||||
|
</template>
|
||||||
|
</InputText>
|
||||||
<button
|
<button
|
||||||
v-if="modelValue && !disabled && !readonly"
|
v-if="modelValue && !disabled && !readonly"
|
||||||
type="button"
|
type="button"
|
||||||
class="absolute right-2 text-slate-400 hover:text-slate-600 text-xs font-bold w-4 h-4 rounded-full flex items-center justify-center bg-slate-100 hover:bg-slate-200 transition"
|
class="absolute right-2 text-slate-400 hover:text-slate-600 text-xs font-bold w-4 h-4 rounded-full flex items-center justify-center bg-slate-100 hover:bg-slate-200 transition"
|
||||||
title="Clear text"
|
title="1-Click 삭제"
|
||||||
@click="onClear"
|
@click="onClear"
|
||||||
>
|
>
|
||||||
✕
|
✕
|
||||||
@@ -26,6 +31,10 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import InputText from 'primevue/inputtext';
|
import InputText from 'primevue/inputtext';
|
||||||
|
|
||||||
|
defineOptions({
|
||||||
|
inheritAttrs: false
|
||||||
|
});
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
id?: string;
|
id?: string;
|
||||||
type?: string;
|
type?: string;
|
||||||
|
|||||||
Reference in New Issue
Block a user