style(ui): standardize font colors across 4-layer components to slate-800 labels and slate-900 input values
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 19s
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 10s
Validators (Pushes and Pull Requests) / CI Workflow Lint (push) Failing after 9s
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 19s
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 10s
Validators (Pushes and Pull Requests) / CI Workflow Lint (push) Failing after 9s
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
<!-- Domain Field Component Layer: MoneyField (WBS-COMP-3.2) -->
|
||||
<template>
|
||||
<div class="domain-money-field flex flex-col gap-1">
|
||||
<label v-if="label" class="text-xs font-bold text-slate-700">
|
||||
{{ label }} <span v-if="required" class="text-red-500">*</span>
|
||||
<div class="domain-money-field flex flex-col gap-1 w-full">
|
||||
<label v-if="label" class="text-xs font-bold text-slate-800">
|
||||
{{ label }} <span v-if="required" class="text-rose-600">*</span>
|
||||
</label>
|
||||
<div class="flex gap-2">
|
||||
<input
|
||||
@@ -11,13 +11,13 @@
|
||||
placeholder="0"
|
||||
:readonly="readonly"
|
||||
:disabled="disabled"
|
||||
class="flex-1 h-9 px-3 border border-slate-300 rounded text-right font-mono text-xs text-slate-800 font-bold focus:ring-2 focus:ring-blue-500 focus:outline-none"
|
||||
class="flex-1 h-9 px-3 border border-slate-300 rounded text-right font-mono text-xs text-slate-900 font-bold bg-white focus:ring-2 focus:ring-blue-500 focus:border-blue-500 focus:outline-none disabled:bg-slate-100 disabled:text-slate-500 readonly:bg-slate-50 readonly:text-slate-700"
|
||||
@input="handleInput"
|
||||
/>
|
||||
<select
|
||||
:value="currencyCode || 'KRW'"
|
||||
:disabled="currencyReadonly || disabled"
|
||||
class="h-9 px-2 border border-slate-300 rounded bg-slate-50 text-xs font-bold text-slate-700"
|
||||
class="h-9 px-2 border border-slate-300 rounded bg-slate-50 text-xs font-bold text-slate-800"
|
||||
@change="handleCurrencyChange"
|
||||
>
|
||||
<option value="KRW">KRW (₩)</option>
|
||||
@@ -26,7 +26,7 @@
|
||||
<option value="JPY">JPY (¥)</option>
|
||||
</select>
|
||||
</div>
|
||||
<div v-if="formattedKrwSummary" class="text-[11px] text-blue-600 font-medium mt-0.5">
|
||||
<div v-if="formattedKrwSummary" class="text-[11px] text-blue-700 font-bold mt-0.5">
|
||||
한화 환산: {{ formattedKrwSummary }} 원
|
||||
</div>
|
||||
</div>
|
||||
@@ -58,7 +58,7 @@ const formattedKrwSummary = computed(() => {
|
||||
if (!props.amount || props.currencyCode === 'KRW') return '';
|
||||
const num = Number(props.amount.replace(/,/g, ''));
|
||||
if (isNaN(num)) return '';
|
||||
return (num * 1350).toLocaleString('ko-KR'); // 예시 환율
|
||||
return (num * 1350).toLocaleString('ko-KR');
|
||||
});
|
||||
|
||||
const handleInput = (e: Event) => {
|
||||
|
||||
@@ -1,46 +1,72 @@
|
||||
<!-- Domain Field Component Layer -->
|
||||
<!-- Domain Field Component Layer: QuantityField (WBS-COMP-3.1) -->
|
||||
<template>
|
||||
<div class="domain-quantity-field">
|
||||
<label class="domain-label">{{ label || '수량' }} <span v-if="required" class="req">*</span></label>
|
||||
<div class="input-unit-group flex gap-2">
|
||||
<div class="domain-quantity-field flex flex-col gap-1 w-full">
|
||||
<div class="flex justify-between items-center text-xs">
|
||||
<label v-if="label" class="font-bold text-slate-800">
|
||||
{{ label }} <span v-if="required" class="text-rose-600">*</span>
|
||||
</label>
|
||||
<span v-if="availableStock !== undefined" class="text-[11px] text-emerald-700 font-bold">
|
||||
가용재고: {{ availableStock.toLocaleString() }} {{ selectedUnit }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="flex gap-2">
|
||||
<input
|
||||
type="text"
|
||||
:value="amount"
|
||||
:value="formattedAmount"
|
||||
placeholder="0"
|
||||
class="quantity-input flex-1 border rounded px-3 py-1 text-right font-mono"
|
||||
@input="handleAmountInput"
|
||||
:readonly="readonly"
|
||||
:disabled="disabled"
|
||||
class="flex-1 h-9 px-3 border border-slate-300 rounded text-right font-mono text-xs text-slate-900 font-bold bg-white focus:ring-2 focus:ring-blue-500 focus:border-blue-500 focus:outline-none disabled:bg-slate-100 disabled:text-slate-500 readonly:bg-slate-50 readonly:text-slate-700"
|
||||
@input="handleInput"
|
||||
/>
|
||||
<select :value="unitCode" class="unit-select border rounded px-2" @change="handleUnitChange">
|
||||
<option v-for="unit in availableUnits" :key="unit" :value="unit">{{ unit }}</option>
|
||||
<select
|
||||
:value="selectedUnit"
|
||||
:disabled="unitReadonly || disabled"
|
||||
class="h-9 px-2 border border-slate-300 rounded bg-slate-50 text-xs font-bold text-slate-800"
|
||||
@change="handleUnitChange"
|
||||
>
|
||||
<option v-for="unit in availableUnits || ['EA', 'BOX', 'PALLET']" :key="unit" :value="unit">
|
||||
{{ unit }}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
<div v-if="stockContext" class="stock-info text-xs text-slate-500 mt-1">
|
||||
가용재고: <strong>{{ stockContext.availableAmount }} {{ unitCode }}</strong>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed, ref } from 'vue';
|
||||
|
||||
const props = defineProps<{
|
||||
label?: string;
|
||||
amount: string | number;
|
||||
unitCode?: string;
|
||||
availableUnits?: string[];
|
||||
availableStock?: number;
|
||||
required?: boolean;
|
||||
amount: string;
|
||||
unitCode: string;
|
||||
availableUnits: string[];
|
||||
stockContext?: { availableAmount: string };
|
||||
readonly?: boolean;
|
||||
disabled?: boolean;
|
||||
unitReadonly?: boolean;
|
||||
}>();
|
||||
|
||||
const emit = defineEmits(['update:amount', 'update:unitCode']);
|
||||
|
||||
const handleAmountInput = (e: Event) => {
|
||||
emit('update:amount', (e.target as HTMLInputElement).value);
|
||||
const selectedUnit = ref(props.unitCode || 'EA');
|
||||
|
||||
const formattedAmount = computed(() => {
|
||||
if (!props.amount) return '';
|
||||
const num = Number(String(props.amount).replace(/,/g, ''));
|
||||
if (isNaN(num)) return String(props.amount);
|
||||
return num.toLocaleString('ko-KR');
|
||||
});
|
||||
|
||||
const handleInput = (e: Event) => {
|
||||
const raw = (e.target as HTMLInputElement).value.replace(/,/g, '');
|
||||
emit('update:amount', raw);
|
||||
};
|
||||
|
||||
const handleUnitChange = (e: Event) => {
|
||||
emit('update:unitCode', (e.target as HTMLSelectElement).value);
|
||||
const newUnit = (e.target as HTMLSelectElement).value;
|
||||
selectedUnit.value = newUnit;
|
||||
emit('update:unitCode', newUnit);
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.req { color: #DC2626; }
|
||||
</style>
|
||||
|
||||
@@ -1,59 +1,48 @@
|
||||
<!-- Typed Field Component Layer: DateField (WBS-COMP-2.3) -->
|
||||
<template>
|
||||
<div class="typed-date-field flex flex-col gap-1">
|
||||
<label v-if="label" :for="id" class="text-xs font-bold text-slate-700">
|
||||
{{ label }} <span v-if="required" class="text-red-500">*</span>
|
||||
</label>
|
||||
<div class="flex gap-2 items-center">
|
||||
<input
|
||||
:id="id"
|
||||
type="date"
|
||||
:value="modelValue"
|
||||
:min="minDate"
|
||||
:max="maxDate"
|
||||
:readonly="readonly"
|
||||
:disabled="disabled"
|
||||
class="h-9 px-3 border border-slate-300 rounded text-xs text-slate-800 focus:ring-2 focus:ring-blue-500 focus:outline-none"
|
||||
@change="handleChange"
|
||||
/>
|
||||
<div class="typed-date-field flex flex-col gap-1 w-full">
|
||||
<div class="flex justify-between items-center text-xs">
|
||||
<label v-if="label" class="font-bold text-slate-800">
|
||||
{{ label }} <span v-if="required" class="text-rose-600">*</span>
|
||||
</label>
|
||||
<button
|
||||
v-if="showTodayBtn && !readonly && !disabled"
|
||||
type="button"
|
||||
class="h-9 px-2.5 bg-slate-100 hover:bg-slate-200 border border-slate-300 rounded text-xs text-slate-700 font-medium transition"
|
||||
class="text-[11px] font-bold text-blue-600 hover:text-blue-800 underline"
|
||||
@click="setToday"
|
||||
>
|
||||
오늘
|
||||
</button>
|
||||
</div>
|
||||
<div v-if="errorMessage" class="text-[11px] text-red-600 mt-0.5">{{ errorMessage }}</div>
|
||||
<input
|
||||
type="date"
|
||||
:value="modelValue"
|
||||
:readonly="readonly"
|
||||
:disabled="disabled"
|
||||
class="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 focus:outline-none disabled:bg-slate-100 disabled:text-slate-500 disabled:cursor-not-allowed readonly:bg-slate-50 readonly:text-slate-700"
|
||||
@change="handleChange"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
const props = defineProps<{
|
||||
id?: string;
|
||||
label?: string;
|
||||
modelValue?: string;
|
||||
minDate?: string;
|
||||
maxDate?: string;
|
||||
required?: boolean;
|
||||
readonly?: boolean;
|
||||
disabled?: boolean;
|
||||
showTodayBtn?: boolean;
|
||||
errorMessage?: string;
|
||||
}>();
|
||||
|
||||
const emit = defineEmits(['update:modelValue', 'change']);
|
||||
const emit = defineEmits(['update:modelValue']);
|
||||
|
||||
const handleChange = (e: Event) => {
|
||||
const val = (e.target as HTMLInputElement).value;
|
||||
emit('update:modelValue', val);
|
||||
emit('change', val);
|
||||
emit('update:modelValue', (e.target as HTMLInputElement).value);
|
||||
};
|
||||
|
||||
const setToday = () => {
|
||||
const todayIso = new Date().toISOString().substring(0, 10);
|
||||
emit('update:modelValue', todayIso);
|
||||
emit('change', todayIso);
|
||||
const today = new Date().toISOString().substring(0, 10);
|
||||
emit('update:modelValue', today);
|
||||
};
|
||||
</script>
|
||||
|
||||
@@ -1,59 +1,44 @@
|
||||
<!-- Typed Field Component Layer: NumberField (WBS-COMP-2.2) -->
|
||||
<template>
|
||||
<div class="typed-number-field flex flex-col gap-1">
|
||||
<label v-if="label" :for="id" class="text-xs font-bold text-slate-700">
|
||||
{{ label }} <span v-if="required" class="text-red-500">*</span>
|
||||
<div class="typed-number-field flex flex-col gap-1 w-full">
|
||||
<label v-if="label" class="text-xs font-bold text-slate-800">
|
||||
{{ label }} <span v-if="required" class="text-rose-600">*</span>
|
||||
</label>
|
||||
<div class="relative flex items-center">
|
||||
<input
|
||||
:id="id"
|
||||
type="text"
|
||||
:value="displayFormattedValue"
|
||||
:placeholder="placeholder || '0'"
|
||||
:readonly="readonly"
|
||||
:disabled="disabled"
|
||||
class="w-full h-9 px-3 border border-slate-300 rounded text-right font-mono text-xs focus:ring-2 focus:ring-blue-500 focus:outline-none"
|
||||
@input="handleInput"
|
||||
@blur="handleBlur"
|
||||
/>
|
||||
</div>
|
||||
<div v-if="errorMessage" class="text-[11px] text-red-600 mt-0.5">{{ errorMessage }}</div>
|
||||
<input
|
||||
type="text"
|
||||
:value="formattedValue"
|
||||
:placeholder="placeholder || '0'"
|
||||
:readonly="readonly"
|
||||
:disabled="disabled"
|
||||
class="w-full h-9 px-3 border border-slate-300 rounded text-right font-mono text-xs text-slate-900 font-bold 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"
|
||||
@input="handleInput"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed, ref } from 'vue';
|
||||
import { computed } from 'vue';
|
||||
|
||||
const props = defineProps<{
|
||||
id?: string;
|
||||
label?: string;
|
||||
modelValue?: string | number;
|
||||
placeholder?: string;
|
||||
required?: boolean;
|
||||
readonly?: boolean;
|
||||
disabled?: boolean;
|
||||
grouping?: boolean;
|
||||
errorMessage?: string;
|
||||
}>();
|
||||
|
||||
const emit = defineEmits(['update:modelValue', 'change']);
|
||||
const isFocused = ref(false);
|
||||
const emit = defineEmits(['update:modelValue']);
|
||||
|
||||
const displayFormattedValue = computed(() => {
|
||||
if (props.modelValue === null || props.modelValue === undefined || props.modelValue === '') return '';
|
||||
if (isFocused.value) return String(props.modelValue);
|
||||
const num = Number(props.modelValue);
|
||||
const formattedValue = computed(() => {
|
||||
if (props.modelValue === undefined || props.modelValue === null || props.modelValue === '') return '';
|
||||
const num = Number(String(props.modelValue).replace(/,/g, ''));
|
||||
if (isNaN(num)) return String(props.modelValue);
|
||||
return props.grouping !== false ? num.toLocaleString('ko-KR') : String(num);
|
||||
return num.toLocaleString('ko-KR');
|
||||
});
|
||||
|
||||
const handleInput = (e: Event) => {
|
||||
const val = (e.target as HTMLInputElement).value.replace(/,/g, '');
|
||||
emit('update:modelValue', val);
|
||||
emit('change', val);
|
||||
};
|
||||
|
||||
const handleBlur = () => {
|
||||
isFocused.value = false;
|
||||
const raw = (e.target as HTMLInputElement).value.replace(/,/g, '');
|
||||
emit('update:modelValue', raw);
|
||||
};
|
||||
</script>
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
<!-- Typed Field Component Layer -->
|
||||
<!-- Typed Field Component Layer: StringField -->
|
||||
<template>
|
||||
<div class="typed-string-field">
|
||||
<label v-if="label" :for="id" class="field-label">{{ label }}</label>
|
||||
<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 }} <span v-if="required" class="text-rose-600">*</span>
|
||||
</label>
|
||||
<input
|
||||
:id="id"
|
||||
type="text"
|
||||
@@ -9,10 +11,10 @@
|
||||
:placeholder="placeholder"
|
||||
:readonly="readonly"
|
||||
:disabled="disabled"
|
||||
class="string-input"
|
||||
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"
|
||||
@input="handleInput"
|
||||
/>
|
||||
<div v-if="errorMessage" class="field-error-msg">{{ errorMessage }}</div>
|
||||
<div v-if="errorMessage" class="text-[11px] text-rose-600 font-semibold mt-0.5">{{ errorMessage }}</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -22,6 +24,7 @@ const props = defineProps<{
|
||||
label?: string;
|
||||
modelValue?: string;
|
||||
placeholder?: string;
|
||||
required?: boolean;
|
||||
readonly?: boolean;
|
||||
disabled?: boolean;
|
||||
errorMessage?: string;
|
||||
@@ -35,25 +38,3 @@ const handleInput = (e: Event) => {
|
||||
emit('change', val);
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.field-label {
|
||||
display: block;
|
||||
font-size: 12px;
|
||||
font-weight: 700;
|
||||
color: #334155;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
.string-input {
|
||||
width: 100%;
|
||||
height: 36px;
|
||||
padding: 0 10px;
|
||||
border: 1px solid #CBD5E1;
|
||||
border-radius: 4px;
|
||||
}
|
||||
.field-error-msg {
|
||||
font-size: 11px;
|
||||
color: #DC2626;
|
||||
margin-top: 2px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<!-- Primitive UI Components Layer -->
|
||||
<template>
|
||||
<div class="primitive-input-wrapper">
|
||||
<div class="primitive-input-wrapper w-full">
|
||||
<input
|
||||
:id="id"
|
||||
:type="type || 'text'"
|
||||
@@ -8,7 +8,7 @@
|
||||
:placeholder="placeholder"
|
||||
:disabled="disabled"
|
||||
:readonly="readonly"
|
||||
class="primitive-input"
|
||||
class="primitive-input 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"
|
||||
@input="$emit('update:modelValue', ($event.target as HTMLInputElement).value)"
|
||||
/>
|
||||
</div>
|
||||
@@ -26,14 +26,3 @@ defineProps<{
|
||||
|
||||
defineEmits(['update:modelValue']);
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.primitive-input {
|
||||
width: 100%;
|
||||
height: 36px;
|
||||
padding: 0 12px;
|
||||
border: 1px solid #CBD5E1;
|
||||
border-radius: 4px;
|
||||
font-size: 13px;
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user