import { ref, computed } from 'vue'; import { useRouter } from 'vue-router'; const router = useRouter(); const isLoading = ref(false); const jobId = ref(null); const form = ref({ dataSource: 'KRX', fromDate: new Date(Date.now() - 365 * 24 * 60 * 60 * 1000).toISOString().split('T')[0], toDate: new Date().toISOString().split('T')[0], }); const minDate = '2015-01-01'; // KRX historical data starts here const maxDate = new Date().toISOString().split('T')[0]; // Today const validationErrors = computed(() => { const errors = []; if (!form.value.fromDate) errors.push('From Date is required'); if (!form.value.toDate) errors.push('To Date is required'); if (form.value.fromDate && form.value.toDate) { if (form.value.fromDate > form.value.toDate) { errors.push('From Date must be before To Date'); } if (form.value.toDate > maxDate) { errors.push('To Date cannot be in the future'); } } return errors; }); const daysCount = computed(() => { if (!form.value.fromDate || !form.value.toDate) return 0; const from = new Date(form.value.fromDate); const to = new Date(form.value.toDate); return Math.ceil((to.getTime() - from.getTime()) / (1000 * 60 * 60 * 24)); }); const estimatedRows = computed(() => { // KRX: ~2000 stocks × days // OpenDart: ~200 quarterly filings if (form.value.dataSource === 'KRX') { return (daysCount.value * 2000).toLocaleString(); } else if (form.value.dataSource === 'OpenDart') { return (Math.ceil(daysCount.value / 90) * 200).toLocaleString(); } return '0'; }); const setPreset = (preset) => { const today = new Date(); const from = new Date(); if (preset === '1y') from.setFullYear(from.getFullYear() - 1); else if (preset === '2y') from.setFullYear(from.getFullYear() - 2); else if (preset === '5y') from.setFullYear(from.getFullYear() - 5); else if (preset === 'all') from.setFullYear(2015); form.value.fromDate = from.toISOString().split('T')[0]; form.value.toDate = today.toISOString().split('T')[0]; }; const triggerIngestion = async () => { if (validationErrors.value.length > 0) return; isLoading.value = true; try { const response = await fetch('/api/market/ingest', { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-KArtSell-User': 'ingestion-user', 'X-KArtSell-Role': 'DataAdmin', }, body: JSON.stringify({ dataSource: form.value.dataSource, fromDate: form.value.fromDate, toDate: form.value.toDate, }), }); if (!response.ok) { throw new Error(`HTTP ${response.status}`); } const data = await response.json(); jobId.value = data.jobId; // Reset form after success setTimeout(() => { form.value.fromDate = new Date(Date.now() - 365 * 24 * 60 * 60 * 1000).toISOString().split('T')[0]; form.value.toDate = new Date().toISOString().split('T')[0]; jobId.value = null; }, 5000); } catch (error) { console.error('Ingestion error:', error); alert(`Failed to trigger ingestion: ${error instanceof Error ? error.message : 'Unknown error'}`); } finally { isLoading.value = false; } }; const resetForm = () => { form.value = { dataSource: 'KRX', fromDate: new Date(Date.now() - 365 * 24 * 60 * 60 * 1000).toISOString().split('T')[0], toDate: new Date().toISOString().split('T')[0], }; jobId.value = null; }; const __VLS_ctx = { ...{}, ...{}, }; let __VLS_components; let __VLS_intrinsics; let __VLS_directives; /** @type {__VLS_StyleScopedClasses['header']} */ ; /** @type {__VLS_StyleScopedClasses['config-card']} */ ; /** @type {__VLS_StyleScopedClasses['summary-card']} */ ; /** @type {__VLS_StyleScopedClasses['error-card']} */ ; /** @type {__VLS_StyleScopedClasses['success-card']} */ ; /** @type {__VLS_StyleScopedClasses['form-group']} */ ; /** @type {__VLS_StyleScopedClasses['form-group']} */ ; /** @type {__VLS_StyleScopedClasses['form-group']} */ ; /** @type {__VLS_StyleScopedClasses['preset-btn']} */ ; /** @type {__VLS_StyleScopedClasses['summary-item']} */ ; /** @type {__VLS_StyleScopedClasses['summary-item']} */ ; /** @type {__VLS_StyleScopedClasses['error-card']} */ ; /** @type {__VLS_StyleScopedClasses['error-card']} */ ; /** @type {__VLS_StyleScopedClasses['error-card']} */ ; /** @type {__VLS_StyleScopedClasses['error-card']} */ ; /** @type {__VLS_StyleScopedClasses['success-card']} */ ; /** @type {__VLS_StyleScopedClasses['success-card']} */ ; /** @type {__VLS_StyleScopedClasses['job-info']} */ ; /** @type {__VLS_StyleScopedClasses['job-info']} */ ; /** @type {__VLS_StyleScopedClasses['btn-primary']} */ ; /** @type {__VLS_StyleScopedClasses['btn-primary']} */ ; /** @type {__VLS_StyleScopedClasses['btn-primary']} */ ; /** @type {__VLS_StyleScopedClasses['btn-secondary']} */ ; /** @type {__VLS_StyleScopedClasses['btn-secondary']} */ ; /** @type {__VLS_StyleScopedClasses['btn-link']} */ ; /** @type {__VLS_StyleScopedClasses['btn-link']} */ ; __VLS_asFunctionalElement1(__VLS_intrinsics.div, __VLS_intrinsics.div)({ ...{ class: "market-data-ingestion" }, }); /** @type {__VLS_StyleScopedClasses['market-data-ingestion']} */ ; __VLS_asFunctionalElement1(__VLS_intrinsics.div, __VLS_intrinsics.div)({ ...{ class: "header" }, }); /** @type {__VLS_StyleScopedClasses['header']} */ ; __VLS_asFunctionalElement1(__VLS_intrinsics.h1, __VLS_intrinsics.h1)({}); __VLS_asFunctionalElement1(__VLS_intrinsics.p, __VLS_intrinsics.p)({ ...{ class: "subtitle" }, }); /** @type {__VLS_StyleScopedClasses['subtitle']} */ ; __VLS_asFunctionalElement1(__VLS_intrinsics.div, __VLS_intrinsics.div)({ ...{ class: "content" }, }); /** @type {__VLS_StyleScopedClasses['content']} */ ; __VLS_asFunctionalElement1(__VLS_intrinsics.div, __VLS_intrinsics.div)({ ...{ class: "config-card" }, }); /** @type {__VLS_StyleScopedClasses['config-card']} */ ; __VLS_asFunctionalElement1(__VLS_intrinsics.h2, __VLS_intrinsics.h2)({}); __VLS_asFunctionalElement1(__VLS_intrinsics.div, __VLS_intrinsics.div)({ ...{ class: "form-group" }, }); /** @type {__VLS_StyleScopedClasses['form-group']} */ ; __VLS_asFunctionalElement1(__VLS_intrinsics.label, __VLS_intrinsics.label)({}); __VLS_asFunctionalElement1(__VLS_intrinsics.select, __VLS_intrinsics.select)({ value: (__VLS_ctx.form.dataSource), }); __VLS_asFunctionalElement1(__VLS_intrinsics.option, __VLS_intrinsics.option)({ value: "KRX", }); __VLS_asFunctionalElement1(__VLS_intrinsics.option, __VLS_intrinsics.option)({ value: "OpenDart", }); __VLS_asFunctionalElement1(__VLS_intrinsics.option, __VLS_intrinsics.option)({ value: "Stub", }); __VLS_asFunctionalElement1(__VLS_intrinsics.p, __VLS_intrinsics.p)({ ...{ class: "hint" }, }); /** @type {__VLS_StyleScopedClasses['hint']} */ ; __VLS_asFunctionalElement1(__VLS_intrinsics.strong, __VLS_intrinsics.strong)({}); __VLS_asFunctionalElement1(__VLS_intrinsics.strong, __VLS_intrinsics.strong)({}); __VLS_asFunctionalElement1(__VLS_intrinsics.div, __VLS_intrinsics.div)({ ...{ class: "form-row" }, }); /** @type {__VLS_StyleScopedClasses['form-row']} */ ; __VLS_asFunctionalElement1(__VLS_intrinsics.div, __VLS_intrinsics.div)({ ...{ class: "form-group" }, }); /** @type {__VLS_StyleScopedClasses['form-group']} */ ; __VLS_asFunctionalElement1(__VLS_intrinsics.label, __VLS_intrinsics.label)({}); __VLS_asFunctionalElement1(__VLS_intrinsics.input)({ type: "date", min: (__VLS_ctx.minDate), max: (__VLS_ctx.maxDate), placeholder: "YYYY-MM-DD", }); (__VLS_ctx.form.fromDate); __VLS_asFunctionalElement1(__VLS_intrinsics.p, __VLS_intrinsics.p)({ ...{ class: "hint" }, }); /** @type {__VLS_StyleScopedClasses['hint']} */ ; (__VLS_ctx.minDate); __VLS_asFunctionalElement1(__VLS_intrinsics.div, __VLS_intrinsics.div)({ ...{ class: "form-group" }, }); /** @type {__VLS_StyleScopedClasses['form-group']} */ ; __VLS_asFunctionalElement1(__VLS_intrinsics.label, __VLS_intrinsics.label)({}); __VLS_asFunctionalElement1(__VLS_intrinsics.input)({ type: "date", min: (__VLS_ctx.form.fromDate || __VLS_ctx.minDate), max: (__VLS_ctx.maxDate), placeholder: "YYYY-MM-DD", }); (__VLS_ctx.form.toDate); __VLS_asFunctionalElement1(__VLS_intrinsics.p, __VLS_intrinsics.p)({ ...{ class: "hint" }, }); /** @type {__VLS_StyleScopedClasses['hint']} */ ; (__VLS_ctx.maxDate); __VLS_asFunctionalElement1(__VLS_intrinsics.div, __VLS_intrinsics.div)({ ...{ class: "presets" }, }); /** @type {__VLS_StyleScopedClasses['presets']} */ ; __VLS_asFunctionalElement1(__VLS_intrinsics.button, __VLS_intrinsics.button)({ ...{ onClick: (...[$event]) => { return (__VLS_ctx.setPreset('1y')); // @ts-ignore [form, form, form, form, minDate, minDate, minDate, maxDate, maxDate, maxDate, setPreset,]; } }, ...{ class: "preset-btn" }, }); /** @type {__VLS_StyleScopedClasses['preset-btn']} */ ; __VLS_asFunctionalElement1(__VLS_intrinsics.button, __VLS_intrinsics.button)({ ...{ onClick: (...[$event]) => { return (__VLS_ctx.setPreset('2y')); // @ts-ignore [setPreset,]; } }, ...{ class: "preset-btn" }, }); /** @type {__VLS_StyleScopedClasses['preset-btn']} */ ; __VLS_asFunctionalElement1(__VLS_intrinsics.button, __VLS_intrinsics.button)({ ...{ onClick: (...[$event]) => { return (__VLS_ctx.setPreset('5y')); // @ts-ignore [setPreset,]; } }, ...{ class: "preset-btn" }, }); /** @type {__VLS_StyleScopedClasses['preset-btn']} */ ; __VLS_asFunctionalElement1(__VLS_intrinsics.button, __VLS_intrinsics.button)({ ...{ onClick: (...[$event]) => { return (__VLS_ctx.setPreset('all')); // @ts-ignore [setPreset,]; } }, ...{ class: "preset-btn" }, }); /** @type {__VLS_StyleScopedClasses['preset-btn']} */ ; if (__VLS_ctx.validationErrors.length) { __VLS_asFunctionalElement1(__VLS_intrinsics.div, __VLS_intrinsics.div)({ ...{ class: "error-card" }, }); /** @type {__VLS_StyleScopedClasses['error-card']} */ ; __VLS_asFunctionalElement1(__VLS_intrinsics.h3, __VLS_intrinsics.h3)({}); __VLS_asFunctionalElement1(__VLS_intrinsics.ul, __VLS_intrinsics.ul)({}); for (const [err, idx] of __VLS_vFor((__VLS_ctx.validationErrors))) { __VLS_asFunctionalElement1(__VLS_intrinsics.li, __VLS_intrinsics.li)({ key: (idx), }); (err); // @ts-ignore [validationErrors, validationErrors,]; } } if (!__VLS_ctx.validationErrors.length) { __VLS_asFunctionalElement1(__VLS_intrinsics.div, __VLS_intrinsics.div)({ ...{ class: "summary-card" }, }); /** @type {__VLS_StyleScopedClasses['summary-card']} */ ; __VLS_asFunctionalElement1(__VLS_intrinsics.h3, __VLS_intrinsics.h3)({}); __VLS_asFunctionalElement1(__VLS_intrinsics.div, __VLS_intrinsics.div)({ ...{ class: "summary-grid" }, }); /** @type {__VLS_StyleScopedClasses['summary-grid']} */ ; __VLS_asFunctionalElement1(__VLS_intrinsics.div, __VLS_intrinsics.div)({ ...{ class: "summary-item" }, }); /** @type {__VLS_StyleScopedClasses['summary-item']} */ ; __VLS_asFunctionalElement1(__VLS_intrinsics.span, __VLS_intrinsics.span)({ ...{ class: "label" }, }); /** @type {__VLS_StyleScopedClasses['label']} */ ; __VLS_asFunctionalElement1(__VLS_intrinsics.span, __VLS_intrinsics.span)({ ...{ class: "value" }, }); /** @type {__VLS_StyleScopedClasses['value']} */ ; (__VLS_ctx.form.dataSource); __VLS_asFunctionalElement1(__VLS_intrinsics.div, __VLS_intrinsics.div)({ ...{ class: "summary-item" }, }); /** @type {__VLS_StyleScopedClasses['summary-item']} */ ; __VLS_asFunctionalElement1(__VLS_intrinsics.span, __VLS_intrinsics.span)({ ...{ class: "label" }, }); /** @type {__VLS_StyleScopedClasses['label']} */ ; __VLS_asFunctionalElement1(__VLS_intrinsics.span, __VLS_intrinsics.span)({ ...{ class: "value" }, }); /** @type {__VLS_StyleScopedClasses['value']} */ ; (__VLS_ctx.form.fromDate); (__VLS_ctx.form.toDate); __VLS_asFunctionalElement1(__VLS_intrinsics.div, __VLS_intrinsics.div)({ ...{ class: "summary-item" }, }); /** @type {__VLS_StyleScopedClasses['summary-item']} */ ; __VLS_asFunctionalElement1(__VLS_intrinsics.span, __VLS_intrinsics.span)({ ...{ class: "label" }, }); /** @type {__VLS_StyleScopedClasses['label']} */ ; __VLS_asFunctionalElement1(__VLS_intrinsics.span, __VLS_intrinsics.span)({ ...{ class: "value" }, }); /** @type {__VLS_StyleScopedClasses['value']} */ ; (__VLS_ctx.daysCount); __VLS_asFunctionalElement1(__VLS_intrinsics.div, __VLS_intrinsics.div)({ ...{ class: "summary-item" }, }); /** @type {__VLS_StyleScopedClasses['summary-item']} */ ; __VLS_asFunctionalElement1(__VLS_intrinsics.span, __VLS_intrinsics.span)({ ...{ class: "label" }, }); /** @type {__VLS_StyleScopedClasses['label']} */ ; __VLS_asFunctionalElement1(__VLS_intrinsics.span, __VLS_intrinsics.span)({ ...{ class: "value" }, }); /** @type {__VLS_StyleScopedClasses['value']} */ ; (__VLS_ctx.estimatedRows); } __VLS_asFunctionalElement1(__VLS_intrinsics.div, __VLS_intrinsics.div)({ ...{ class: "actions" }, }); /** @type {__VLS_StyleScopedClasses['actions']} */ ; __VLS_asFunctionalElement1(__VLS_intrinsics.button, __VLS_intrinsics.button)({ ...{ onClick: (__VLS_ctx.triggerIngestion) }, disabled: (__VLS_ctx.isLoading || __VLS_ctx.validationErrors.length > 0), ...{ class: "btn-primary" }, }); /** @type {__VLS_StyleScopedClasses['btn-primary']} */ ; if (!__VLS_ctx.isLoading) { __VLS_asFunctionalElement1(__VLS_intrinsics.span, __VLS_intrinsics.span)({}); } else { __VLS_asFunctionalElement1(__VLS_intrinsics.span, __VLS_intrinsics.span)({}); } __VLS_asFunctionalElement1(__VLS_intrinsics.button, __VLS_intrinsics.button)({ ...{ onClick: (__VLS_ctx.resetForm) }, ...{ class: "btn-secondary" }, }); /** @type {__VLS_StyleScopedClasses['btn-secondary']} */ ; if (__VLS_ctx.jobId) { __VLS_asFunctionalElement1(__VLS_intrinsics.div, __VLS_intrinsics.div)({ ...{ class: "success-card" }, }); /** @type {__VLS_StyleScopedClasses['success-card']} */ ; __VLS_asFunctionalElement1(__VLS_intrinsics.h3, __VLS_intrinsics.h3)({}); __VLS_asFunctionalElement1(__VLS_intrinsics.div, __VLS_intrinsics.div)({ ...{ class: "job-info" }, }); /** @type {__VLS_StyleScopedClasses['job-info']} */ ; __VLS_asFunctionalElement1(__VLS_intrinsics.p, __VLS_intrinsics.p)({}); __VLS_asFunctionalElement1(__VLS_intrinsics.strong, __VLS_intrinsics.strong)({}); (__VLS_ctx.jobId); __VLS_asFunctionalElement1(__VLS_intrinsics.p, __VLS_intrinsics.p)({}); __VLS_asFunctionalElement1(__VLS_intrinsics.strong, __VLS_intrinsics.strong)({}); __VLS_asFunctionalElement1(__VLS_intrinsics.p, __VLS_intrinsics.p)({}); __VLS_asFunctionalElement1(__VLS_intrinsics.strong, __VLS_intrinsics.strong)({}); (new Date().toLocaleString()); __VLS_asFunctionalElement1(__VLS_intrinsics.p, __VLS_intrinsics.p)({ ...{ class: "hint" }, }); /** @type {__VLS_StyleScopedClasses['hint']} */ ; let __VLS_0; /** @ts-ignore @type { | typeof __VLS_components.routerLink | typeof __VLS_components.RouterLink | typeof __VLS_components['router-link'] | typeof __VLS_components.routerLink | typeof __VLS_components.RouterLink | typeof __VLS_components['router-link']} */ routerLink; // @ts-ignore const __VLS_1 = __VLS_asFunctionalComponent1(__VLS_0, new __VLS_0({ to: "/ops/market-data-history", ...{ class: "btn-link" }, })); const __VLS_2 = __VLS_1({ to: "/ops/market-data-history", ...{ class: "btn-link" }, }, ...__VLS_functionalComponentArgsRest(__VLS_1)); /** @type {__VLS_StyleScopedClasses['btn-link']} */ ; const { default: __VLS_5 } = __VLS_3.slots; // @ts-ignore [form, form, form, validationErrors, validationErrors, daysCount, estimatedRows, triggerIngestion, isLoading, isLoading, resetForm, jobId, jobId,]; var __VLS_3; } // @ts-ignore []; const __VLS_export = (await import('vue')).defineComponent({}); export default {};