chore: update .gitignore and remove quick insert options from button configurations
- Added new entries to .gitignore for multi-agent MCP task queue and related rules. - Removed "즉시 저장" (quick insert) options from the ScreenSettingModal and BasicTab components to streamline button configurations. - Cleaned up unused event options in the V2ButtonConfigPanel to enhance clarity and maintainability. These changes aim to improve project organization and simplify the user interface by eliminating redundant options.
This commit is contained in:
parent
2976cad0a5
commit
ae4fe7a66e
|
|
@ -182,3 +182,9 @@ scripts/browser-test-*.js
|
|||
# 개인 작업 문서
|
||||
popdocs/
|
||||
.cursor/rules/popdocs-safety.mdc
|
||||
|
||||
# 멀티 에이전트 MCP 태스크 큐
|
||||
mcp-task-queue/
|
||||
.cursor/rules/multi-agent-pm.mdc
|
||||
.cursor/rules/multi-agent-worker.mdc
|
||||
.cursor/rules/multi-agent-tester.mdc
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import "dotenv/config";
|
||||
process.env.TZ = "Asia/Seoul";
|
||||
import "express-async-errors"; // async 라우트 핸들러의 에러를 Express 에러 핸들러로 자동 전달
|
||||
import express from "express";
|
||||
import cors from "cors";
|
||||
|
|
|
|||
|
|
@ -66,8 +66,9 @@ export const initializePool = (): Pool => {
|
|||
|
||||
// 연결 풀 이벤트 핸들러
|
||||
pool.on("connect", (client) => {
|
||||
client.query("SET timezone = 'Asia/Seoul'");
|
||||
if (config.debug) {
|
||||
console.log("✅ PostgreSQL 클라이언트 연결 생성");
|
||||
console.log("✅ PostgreSQL 클라이언트 연결 생성 (timezone: Asia/Seoul)");
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -82,7 +82,8 @@ export function DashboardTopMenu({
|
|||
) => {
|
||||
if (format === "png") {
|
||||
const link = document.createElement("a");
|
||||
const filename = `${dashboardTitle || "dashboard"}_${new Date().toISOString().split("T")[0]}.png`;
|
||||
const _fd = new Date();
|
||||
const filename = `${dashboardTitle || "dashboard"}_${_fd.getFullYear()}-${String(_fd.getMonth() + 1).padStart(2, "0")}-${String(_fd.getDate()).padStart(2, "0")}.png`;
|
||||
link.download = filename;
|
||||
link.href = dataUrl;
|
||||
document.body.appendChild(link);
|
||||
|
|
@ -111,7 +112,8 @@ export function DashboardTopMenu({
|
|||
});
|
||||
|
||||
pdf.addImage(dataUrl, "PNG", 0, 0, imgWidth, imgHeight);
|
||||
const filename = `${dashboardTitle || "dashboard"}_${new Date().toISOString().split("T")[0]}.pdf`;
|
||||
const _pd = new Date();
|
||||
const filename = `${dashboardTitle || "dashboard"}_${_pd.getFullYear()}-${String(_pd.getMonth() + 1).padStart(2, "0")}-${String(_pd.getDate()).padStart(2, "0")}.pdf`;
|
||||
pdf.save(filename);
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -100,36 +100,37 @@ export function getQuickDateRange(range: "today" | "week" | "month" | "year"): {
|
|||
} {
|
||||
const now = new Date();
|
||||
const today = new Date(now.getFullYear(), now.getMonth(), now.getDate());
|
||||
const fmtDate = (d: Date) => `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, "0")}-${String(d.getDate()).padStart(2, "0")}`;
|
||||
|
||||
switch (range) {
|
||||
case "today":
|
||||
return {
|
||||
startDate: today.toISOString().split("T")[0],
|
||||
endDate: today.toISOString().split("T")[0],
|
||||
startDate: fmtDate(today),
|
||||
endDate: fmtDate(today),
|
||||
};
|
||||
|
||||
case "week": {
|
||||
const weekStart = new Date(today);
|
||||
weekStart.setDate(today.getDate() - today.getDay()); // 일요일부터
|
||||
weekStart.setDate(today.getDate() - today.getDay());
|
||||
return {
|
||||
startDate: weekStart.toISOString().split("T")[0],
|
||||
endDate: today.toISOString().split("T")[0],
|
||||
startDate: fmtDate(weekStart),
|
||||
endDate: fmtDate(today),
|
||||
};
|
||||
}
|
||||
|
||||
case "month": {
|
||||
const monthStart = new Date(today.getFullYear(), today.getMonth(), 1);
|
||||
return {
|
||||
startDate: monthStart.toISOString().split("T")[0],
|
||||
endDate: today.toISOString().split("T")[0],
|
||||
startDate: fmtDate(monthStart),
|
||||
endDate: fmtDate(today),
|
||||
};
|
||||
}
|
||||
|
||||
case "year": {
|
||||
const yearStart = new Date(today.getFullYear(), 0, 1);
|
||||
return {
|
||||
startDate: yearStart.toISOString().split("T")[0],
|
||||
endDate: today.toISOString().split("T")[0],
|
||||
startDate: fmtDate(yearStart),
|
||||
endDate: fmtDate(today),
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -217,7 +217,8 @@ export function DashboardViewer({
|
|||
if (format === "png") {
|
||||
console.log("💾 PNG 다운로드 시작...");
|
||||
const link = document.createElement("a");
|
||||
const filename = `${dashboardTitle || "dashboard"}_${new Date().toISOString().split("T")[0]}.png`;
|
||||
const _dvd = new Date();
|
||||
const filename = `${dashboardTitle || "dashboard"}_${_dvd.getFullYear()}-${String(_dvd.getMonth() + 1).padStart(2, "0")}-${String(_dvd.getDate()).padStart(2, "0")}.png`;
|
||||
link.download = filename;
|
||||
link.href = dataUrl;
|
||||
document.body.appendChild(link);
|
||||
|
|
@ -253,7 +254,8 @@ export function DashboardViewer({
|
|||
});
|
||||
|
||||
pdf.addImage(dataUrl, "PNG", 0, 0, imgWidth, imgHeight);
|
||||
const filename = `${dashboardTitle || "dashboard"}_${new Date().toISOString().split("T")[0]}.pdf`;
|
||||
const _dvp = new Date();
|
||||
const filename = `${dashboardTitle || "dashboard"}_${_dvp.getFullYear()}-${String(_dvp.getMonth() + 1).padStart(2, "0")}-${String(_dvp.getDate()).padStart(2, "0")}.pdf`;
|
||||
pdf.save(filename);
|
||||
console.log("✅ PDF 다운로드 완료:", filename);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -61,7 +61,8 @@ export default function DeliveryTodayStatsWidget({ element }: DeliveryTodayStats
|
|||
// 데이터 처리
|
||||
if (result.success && result.data?.rows) {
|
||||
const rows = result.data.rows;
|
||||
const today = new Date().toISOString().split("T")[0];
|
||||
const _td = new Date();
|
||||
const today = `${_td.getFullYear()}-${String(_td.getMonth() + 1).padStart(2, "0")}-${String(_td.getDate()).padStart(2, "0")}`;
|
||||
|
||||
// 오늘 발송 건수 (created_at 기준)
|
||||
const shippedToday = rows.filter((row: any) => {
|
||||
|
|
|
|||
|
|
@ -101,7 +101,7 @@ export default function MapTestWidgetV2({ element }: MapTestWidgetV2Props) {
|
|||
const [routePoints, setRoutePoints] = useState<RoutePoint[]>([]);
|
||||
const [selectedUserId, setSelectedUserId] = useState<string | null>(null);
|
||||
const [routeLoading, setRouteLoading] = useState(false);
|
||||
const [routeDate, setRouteDate] = useState<string>(new Date().toISOString().split("T")[0]); // YYYY-MM-DD 형식
|
||||
const [routeDate, setRouteDate] = useState<string>(() => { const d = new Date(); return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, "0")}-${String(d.getDate()).padStart(2, "0")}`; });
|
||||
|
||||
// 공차/운행 정보 상태
|
||||
const [tripInfo, setTripInfo] = useState<Record<string, any>>({});
|
||||
|
|
|
|||
|
|
@ -1120,7 +1120,8 @@ export function ReportPreviewModal({ isOpen, onClose }: ReportPreviewModalProps)
|
|||
const blob = new Blob([response.data], {
|
||||
type: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
||||
});
|
||||
const timestamp = new Date().toISOString().slice(0, 10);
|
||||
const _rpd = new Date();
|
||||
const timestamp = `${_rpd.getFullYear()}-${String(_rpd.getMonth() + 1).padStart(2, "0")}-${String(_rpd.getDate()).padStart(2, "0")}`;
|
||||
const url = window.URL.createObjectURL(blob);
|
||||
const link = document.createElement("a");
|
||||
link.href = url;
|
||||
|
|
|
|||
|
|
@ -86,13 +86,16 @@ export const EnhancedInteractiveScreenViewer: React.FC<EnhancedInteractiveScreen
|
|||
const generateAutoValue = useCallback(
|
||||
async (autoValueType: string, ruleId?: string): Promise<string> => {
|
||||
const now = new Date();
|
||||
const pad = (n: number) => String(n).padStart(2, "0");
|
||||
const localDate = `${now.getFullYear()}-${pad(now.getMonth() + 1)}-${pad(now.getDate())}`;
|
||||
const localTime = `${pad(now.getHours())}:${pad(now.getMinutes())}:${pad(now.getSeconds())}`;
|
||||
switch (autoValueType) {
|
||||
case "current_datetime":
|
||||
return now.toISOString().slice(0, 19).replace("T", " ");
|
||||
return `${localDate} ${localTime}`;
|
||||
case "current_date":
|
||||
return now.toISOString().slice(0, 10);
|
||||
return localDate;
|
||||
case "current_time":
|
||||
return now.toTimeString().slice(0, 8);
|
||||
return localTime;
|
||||
case "current_user":
|
||||
return userName || "사용자";
|
||||
case "uuid":
|
||||
|
|
|
|||
|
|
@ -1155,13 +1155,16 @@ export const InteractiveDataTable: React.FC<InteractiveDataTableProps> = ({
|
|||
const generateAutoValue = useCallback(
|
||||
(autoValueType: string): string => {
|
||||
const now = new Date();
|
||||
const pad = (n: number) => String(n).padStart(2, "0");
|
||||
const localDate = `${now.getFullYear()}-${pad(now.getMonth() + 1)}-${pad(now.getDate())}`;
|
||||
const localTime = `${pad(now.getHours())}:${pad(now.getMinutes())}:${pad(now.getSeconds())}`;
|
||||
switch (autoValueType) {
|
||||
case "current_datetime":
|
||||
return now.toISOString().slice(0, 19); // YYYY-MM-DDTHH:mm:ss
|
||||
return `${localDate} ${localTime}`;
|
||||
case "current_date":
|
||||
return now.toISOString().slice(0, 10); // YYYY-MM-DD
|
||||
return localDate;
|
||||
case "current_time":
|
||||
return now.toTimeString().slice(0, 8); // HH:mm:ss
|
||||
return localTime;
|
||||
case "current_user":
|
||||
return currentUser?.userName || currentUser?.userId || "unknown_user";
|
||||
case "uuid":
|
||||
|
|
|
|||
|
|
@ -357,13 +357,16 @@ export const InteractiveScreenViewer: React.FC<InteractiveScreenViewerProps> = (
|
|||
// 자동값 생성 함수
|
||||
const generateAutoValue = useCallback(async (autoValueType: string, ruleId?: string): Promise<string> => {
|
||||
const now = new Date();
|
||||
const pad = (n: number) => String(n).padStart(2, "0");
|
||||
const localDate = `${now.getFullYear()}-${pad(now.getMonth() + 1)}-${pad(now.getDate())}`;
|
||||
const localTime = `${pad(now.getHours())}:${pad(now.getMinutes())}:${pad(now.getSeconds())}`;
|
||||
switch (autoValueType) {
|
||||
case "current_datetime":
|
||||
return now.toISOString().slice(0, 19).replace("T", " "); // YYYY-MM-DD HH:mm:ss
|
||||
return `${localDate} ${localTime}`;
|
||||
case "current_date":
|
||||
return now.toISOString().slice(0, 10); // YYYY-MM-DD
|
||||
return localDate;
|
||||
case "current_time":
|
||||
return now.toTimeString().slice(0, 8); // HH:mm:ss
|
||||
return localTime;
|
||||
case "current_user":
|
||||
// 실제 접속중인 사용자명 사용
|
||||
return userName || "사용자"; // 사용자명이 없으면 기본값
|
||||
|
|
|
|||
|
|
@ -183,13 +183,16 @@ export const InteractiveScreenViewerDynamic: React.FC<InteractiveScreenViewerPro
|
|||
const generateAutoValue = useCallback(
|
||||
(autoValueType: string): string => {
|
||||
const now = new Date();
|
||||
const pad = (n: number) => String(n).padStart(2, "0");
|
||||
const localDate = `${now.getFullYear()}-${pad(now.getMonth() + 1)}-${pad(now.getDate())}`;
|
||||
const localTime = `${pad(now.getHours())}:${pad(now.getMinutes())}:${pad(now.getSeconds())}`;
|
||||
switch (autoValueType) {
|
||||
case "current_datetime":
|
||||
return now.toISOString().slice(0, 19).replace("T", " ");
|
||||
return `${localDate} ${localTime}`;
|
||||
case "current_date":
|
||||
return now.toISOString().slice(0, 10);
|
||||
return localDate;
|
||||
case "current_time":
|
||||
return now.toTimeString().slice(0, 8);
|
||||
return localTime;
|
||||
case "current_user":
|
||||
return userName || "사용자";
|
||||
case "uuid":
|
||||
|
|
|
|||
|
|
@ -3852,7 +3852,6 @@ function ControlManagementTab({
|
|||
openModalWithData: "데이터+모달",
|
||||
openRelatedModal: "연관모달",
|
||||
transferData: "데이터전달",
|
||||
quickInsert: "즉시저장",
|
||||
control: "제어흐름",
|
||||
view_table_history: "이력보기",
|
||||
excel_download: "엑셀다운",
|
||||
|
|
|
|||
|
|
@ -56,9 +56,11 @@ export const DateConfigPanel: React.FC<WebTypeConfigPanelProps> = ({
|
|||
// 현재 날짜 설정
|
||||
const setCurrentDate = (field: "minDate" | "maxDate" | "defaultValue") => {
|
||||
const now = new Date();
|
||||
const pad = (n: number) => String(n).padStart(2, "0");
|
||||
const d = `${now.getFullYear()}-${pad(now.getMonth() + 1)}-${pad(now.getDate())}`;
|
||||
const dateString = localConfig.showTime
|
||||
? now.toISOString().slice(0, 16) // YYYY-MM-DDTHH:mm
|
||||
: now.toISOString().slice(0, 10); // YYYY-MM-DD
|
||||
? `${d}T${pad(now.getHours())}:${pad(now.getMinutes())}`
|
||||
: d;
|
||||
updateConfig(field, dateString);
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -263,7 +263,6 @@ export const BasicTab: React.FC<ButtonTabProps> = ({
|
|||
</SelectItem>
|
||||
|
||||
{/* 고급 기능 */}
|
||||
<SelectItem value="quickInsert">즉시 저장</SelectItem>
|
||||
<SelectItem value="control">제어 흐름</SelectItem>
|
||||
<SelectItem value="approval">결재 요청</SelectItem>
|
||||
|
||||
|
|
@ -271,9 +270,6 @@ export const BasicTab: React.FC<ButtonTabProps> = ({
|
|||
<SelectItem value="barcode_scan">바코드 스캔</SelectItem>
|
||||
<SelectItem value="operation_control">운행알림 및 종료</SelectItem>
|
||||
|
||||
{/* 이벤트 버스 */}
|
||||
<SelectItem value="event">이벤트 발송</SelectItem>
|
||||
|
||||
{/* 복사 */}
|
||||
<SelectItem value="copy">복사 (품목코드 초기화)</SelectItem>
|
||||
|
||||
|
|
|
|||
|
|
@ -1018,7 +1018,8 @@ export function FlowWidget({
|
|||
const wb = XLSX.utils.book_new();
|
||||
XLSX.utils.book_append_sheet(wb, ws, "Data");
|
||||
|
||||
const fileName = `${flowName || "flow"}_data_${new Date().toISOString().split("T")[0]}.xlsx`;
|
||||
const _fxd = new Date();
|
||||
const fileName = `${flowName || "flow"}_data_${_fxd.getFullYear()}-${String(_fxd.getMonth() + 1).padStart(2, "0")}-${String(_fxd.getDate()).padStart(2, "0")}.xlsx`;
|
||||
XLSX.writeFile(wb, fileName);
|
||||
|
||||
toast.success(`${exportData.length}개 행이 Excel로 내보내기 되었습니다.`);
|
||||
|
|
@ -1183,7 +1184,8 @@ export function FlowWidget({
|
|||
}
|
||||
}
|
||||
|
||||
const fileName = `${flowName || "flow"}_data_${new Date().toISOString().split("T")[0]}.pdf`;
|
||||
const _fpd = new Date();
|
||||
const fileName = `${flowName || "flow"}_data_${_fpd.getFullYear()}-${String(_fpd.getMonth() + 1).padStart(2, "0")}-${String(_fpd.getDate()).padStart(2, "0")}.pdf`;
|
||||
doc.save(fileName);
|
||||
|
||||
toast.success(`${exportData.length}개 행이 PDF로 내보내기 되었습니다.`, { id: "pdf-export" });
|
||||
|
|
|
|||
|
|
@ -52,8 +52,10 @@ export const DateWidget: React.FC<WebTypeComponentProps> = ({ component, value,
|
|||
const getDefaultValue = (): string => {
|
||||
if (config?.defaultValue === "current") {
|
||||
const now = new Date();
|
||||
if (isDatetime) return now.toISOString().slice(0, 16);
|
||||
return now.toISOString().slice(0, 10);
|
||||
const pad = (n: number) => String(n).padStart(2, "0");
|
||||
const d = `${now.getFullYear()}-${pad(now.getMonth() + 1)}-${pad(now.getDate())}`;
|
||||
if (isDatetime) return `${d}T${pad(now.getHours())}:${pad(now.getMinutes())}`;
|
||||
return d;
|
||||
}
|
||||
return "";
|
||||
};
|
||||
|
|
|
|||
|
|
@ -680,11 +680,15 @@ export const UnifiedRepeater: React.FC<UnifiedRepeaterProps> = ({
|
|||
const now = new Date();
|
||||
|
||||
switch (col.autoFill.type) {
|
||||
case "currentDate":
|
||||
return now.toISOString().split("T")[0]; // YYYY-MM-DD
|
||||
case "currentDate": {
|
||||
const pad = (n: number) => String(n).padStart(2, "0");
|
||||
return `${now.getFullYear()}-${pad(now.getMonth() + 1)}-${pad(now.getDate())}`;
|
||||
}
|
||||
|
||||
case "currentDateTime":
|
||||
return now.toISOString().slice(0, 19).replace("T", " "); // YYYY-MM-DD HH:mm:ss
|
||||
case "currentDateTime": {
|
||||
const pad = (n: number) => String(n).padStart(2, "0");
|
||||
return `${now.getFullYear()}-${pad(now.getMonth() + 1)}-${pad(now.getDate())} ${pad(now.getHours())}:${pad(now.getMinutes())}:${pad(now.getSeconds())}`;
|
||||
}
|
||||
|
||||
case "sequence":
|
||||
return rowIndex + 1; // 1부터 시작하는 순번
|
||||
|
|
|
|||
|
|
@ -1041,12 +1041,15 @@ export const V2Repeater: React.FC<V2RepeaterProps> = ({
|
|||
|
||||
const now = new Date();
|
||||
|
||||
const pad = (n: number) => String(n).padStart(2, "0");
|
||||
const localDate = `${now.getFullYear()}-${pad(now.getMonth() + 1)}-${pad(now.getDate())}`;
|
||||
const localTime = `${pad(now.getHours())}:${pad(now.getMinutes())}:${pad(now.getSeconds())}`;
|
||||
switch (col.autoFill.type) {
|
||||
case "currentDate":
|
||||
return now.toISOString().split("T")[0]; // YYYY-MM-DD
|
||||
return localDate;
|
||||
|
||||
case "currentDateTime":
|
||||
return now.toISOString().slice(0, 19).replace("T", " "); // YYYY-MM-DD HH:mm:ss
|
||||
return `${localDate} ${localTime}`;
|
||||
|
||||
case "sequence":
|
||||
return rowIndex + 1; // 1부터 시작하는 순번
|
||||
|
|
|
|||
|
|
@ -130,12 +130,6 @@ const ACTION_TYPE_CARDS = [
|
|||
title: "엑셀 업로드",
|
||||
description: "엑셀 파일을 올려요",
|
||||
},
|
||||
{
|
||||
value: "quickInsert",
|
||||
icon: Zap,
|
||||
title: "즉시 저장",
|
||||
description: "바로 저장해요",
|
||||
},
|
||||
{
|
||||
value: "approval",
|
||||
icon: Check,
|
||||
|
|
@ -148,12 +142,6 @@ const ACTION_TYPE_CARDS = [
|
|||
title: "제어 흐름",
|
||||
description: "흐름을 제어해요",
|
||||
},
|
||||
{
|
||||
value: "event",
|
||||
icon: Send,
|
||||
title: "이벤트 발송",
|
||||
description: "이벤트를 보내요",
|
||||
},
|
||||
{
|
||||
value: "copy",
|
||||
icon: Copy,
|
||||
|
|
|
|||
|
|
@ -56,10 +56,10 @@ export default function VehicleReport() {
|
|||
// 일별 통계
|
||||
const [dailyData, setDailyData] = useState<DailyStat[]>([]);
|
||||
const [dailyStartDate, setDailyStartDate] = useState(
|
||||
new Date(Date.now() - 30 * 24 * 60 * 60 * 1000).toISOString().split("T")[0]
|
||||
(() => { const d = new Date(Date.now() - 30 * 24 * 60 * 60 * 1000); return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, "0")}-${String(d.getDate()).padStart(2, "0")}`; })()
|
||||
);
|
||||
const [dailyEndDate, setDailyEndDate] = useState(
|
||||
new Date().toISOString().split("T")[0]
|
||||
(() => { const d = new Date(); return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, "0")}-${String(d.getDate()).padStart(2, "0")}`; })()
|
||||
);
|
||||
const [dailyLoading, setDailyLoading] = useState(false);
|
||||
|
||||
|
|
|
|||
|
|
@ -53,7 +53,8 @@ export const DateInputComponent: React.FC<DateInputComponentProps> = ({
|
|||
// 자동생성 로직
|
||||
useEffect(() => {
|
||||
if (finalAutoGeneration?.enabled) {
|
||||
const today = new Date().toISOString().split("T")[0]; // YYYY-MM-DD
|
||||
const n = new Date();
|
||||
const today = `${n.getFullYear()}-${String(n.getMonth() + 1).padStart(2, "0")}-${String(n.getDate()).padStart(2, "0")}`;
|
||||
setAutoGeneratedValue(today);
|
||||
|
||||
// 인터랙티브 모드에서 폼 데이터에도 설정
|
||||
|
|
|
|||
|
|
@ -653,9 +653,9 @@ export function RepeaterTable({
|
|||
if (typeof val === "string" && val.includes("T")) {
|
||||
return val.split("T")[0];
|
||||
}
|
||||
// Date 객체이면 변환
|
||||
// Date 객체이면 로컬 날짜로 변환
|
||||
if (val instanceof Date) {
|
||||
return val.toISOString().split("T")[0];
|
||||
return `${val.getFullYear()}-${String(val.getMonth() + 1).padStart(2, "0")}-${String(val.getDate()).padStart(2, "0")}`;
|
||||
}
|
||||
return String(val);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -448,7 +448,8 @@ export function SimpleRepeaterTableComponent({
|
|||
} else if (col.type === "number") {
|
||||
newRow[col.field] = 0;
|
||||
} else if (col.type === "date") {
|
||||
newRow[col.field] = new Date().toISOString().split("T")[0];
|
||||
const _n = new Date();
|
||||
newRow[col.field] = `${_n.getFullYear()}-${String(_n.getMonth() + 1).padStart(2, "0")}-${String(_n.getDate()).padStart(2, "0")}`;
|
||||
} else {
|
||||
newRow[col.field] = "";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2707,7 +2707,8 @@ export const TableListComponent: React.FC<TableListComponentProps> = ({
|
|||
XLSX.utils.book_append_sheet(wb, ws, tableLabel || "데이터");
|
||||
|
||||
// 파일명 생성
|
||||
const fileName = `${tableLabel || tableConfig.selectedTable || "export"}_${new Date().toISOString().split("T")[0]}.xlsx`;
|
||||
const _en = new Date();
|
||||
const fileName = `${tableLabel || tableConfig.selectedTable || "export"}_${_en.getFullYear()}-${String(_en.getMonth() + 1).padStart(2, "0")}-${String(_en.getDate()).padStart(2, "0")}.xlsx`;
|
||||
|
||||
// 파일 다운로드
|
||||
XLSX.writeFile(wb, fileName);
|
||||
|
|
|
|||
|
|
@ -3006,7 +3006,8 @@ export const TableListComponent: React.FC<TableListComponentProps> = ({
|
|||
XLSX.utils.book_append_sheet(wb, ws, tableLabel || "데이터");
|
||||
|
||||
// 파일명 생성
|
||||
const fileName = `${tableLabel || tableConfig.selectedTable || "export"}_${new Date().toISOString().split("T")[0]}.xlsx`;
|
||||
const _en = new Date();
|
||||
const fileName = `${tableLabel || tableConfig.selectedTable || "export"}_${_en.getFullYear()}-${String(_en.getMonth() + 1).padStart(2, "0")}-${String(_en.getDate()).padStart(2, "0")}.xlsx`;
|
||||
|
||||
// 파일 다운로드
|
||||
XLSX.writeFile(wb, fileName);
|
||||
|
|
|
|||
|
|
@ -227,7 +227,7 @@ export function TimelineSchedulerComponent({
|
|||
if (onCellClick) {
|
||||
onCellClick({
|
||||
resourceId,
|
||||
date: date.toISOString().split("T")[0],
|
||||
date: `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, "0")}-${String(date.getDate()).padStart(2, "0")}`,
|
||||
});
|
||||
}
|
||||
},
|
||||
|
|
@ -343,7 +343,7 @@ export function TimelineSchedulerComponent({
|
|||
if (onAddSchedule && effectiveResources.length > 0) {
|
||||
onAddSchedule(
|
||||
effectiveResources[0].id,
|
||||
new Date().toISOString().split("T")[0]
|
||||
(() => { const _n = new Date(); return `${_n.getFullYear()}-${String(_n.getMonth() + 1).padStart(2, "0")}-${String(_n.getDate()).padStart(2, "0")}`; })()
|
||||
);
|
||||
}
|
||||
}, [onAddSchedule, effectiveResources]);
|
||||
|
|
@ -383,7 +383,8 @@ export function TimelineSchedulerComponent({
|
|||
const items = Array.from(grouped.entries()).map(([code, rows]) => {
|
||||
const totalQty = rows.reduce((sum: number, r: any) => sum + (Number(r[qtyField]) || 0), 0);
|
||||
const dates = rows.map((r: any) => r[dateField]).filter(Boolean).sort();
|
||||
const earliestDate = dates[0] || new Date().toISOString().split("T")[0];
|
||||
const _dn = new Date();
|
||||
const earliestDate = dates[0] || `${_dn.getFullYear()}-${String(_dn.getMonth() + 1).padStart(2, "0")}-${String(_dn.getDate()).padStart(2, "0")}`;
|
||||
const first = rows[0];
|
||||
return {
|
||||
item_code: code,
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ interface ItemTimelineCardProps {
|
|||
onScheduleClick?: (schedule: ScheduleItem) => void;
|
||||
}
|
||||
|
||||
const toDateString = (d: Date) => d.toISOString().split("T")[0];
|
||||
const toDateString = (d: Date) => `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, "0")}-${String(d.getDate()).padStart(2, "0")}`;
|
||||
|
||||
const addDays = (d: Date, n: number) => {
|
||||
const r = new Date(d);
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ const SCHEDULE_TABLE = "schedule_mng";
|
|||
* 날짜를 ISO 문자열로 변환 (시간 제외)
|
||||
*/
|
||||
const toDateString = (date: Date): string => {
|
||||
return date.toISOString().split("T")[0];
|
||||
return `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, "0")}-${String(date.getDate()).padStart(2, "0")}`;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -54,5 +54,5 @@ export function detectConflicts(schedules: ScheduleItem[]): Set<string> {
|
|||
export function addDaysToDateString(dateStr: string, days: number): string {
|
||||
const date = new Date(dateStr);
|
||||
date.setDate(date.getDate() + days);
|
||||
return date.toISOString().split("T")[0];
|
||||
return `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, "0")}-${String(date.getDate()).padStart(2, "0")}`;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -251,7 +251,7 @@ export function computeDateRange(
|
|||
preset: DatePresetOption
|
||||
): { preset: DatePresetOption; from: string; to: string } | null {
|
||||
const now = new Date();
|
||||
const fmt = (d: Date) => d.toISOString().split("T")[0];
|
||||
const fmt = (d: Date) => `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, "0")}-${String(d.getDate()).padStart(2, "0")}`;
|
||||
|
||||
switch (preset) {
|
||||
case "today":
|
||||
|
|
|
|||
|
|
@ -349,7 +349,7 @@ export class EnhancedFormService {
|
|||
|
||||
if (lowerDataType.includes("date")) {
|
||||
const date = new Date(value);
|
||||
return isNaN(date.getTime()) ? null : date.toISOString().split("T")[0];
|
||||
return isNaN(date.getTime()) ? null : `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, "0")}-${String(date.getDate()).padStart(2, "0")}`;
|
||||
}
|
||||
|
||||
if (lowerDataType.includes("time")) {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
"use client";
|
||||
|
||||
import { AutoGenerationType, AutoGenerationConfig } from "@/types/screen";
|
||||
import { toLocalDate, toLocalTime, toLocalDateTime } from "@/lib/utils/localDate";
|
||||
|
||||
/**
|
||||
* 자동생성 값 생성 유틸리티
|
||||
|
|
@ -52,19 +53,19 @@ export class AutoGenerationUtils {
|
|||
let result: string;
|
||||
switch (format) {
|
||||
case "date":
|
||||
result = now.toISOString().split("T")[0]; // YYYY-MM-DD
|
||||
result = toLocalDate(now);
|
||||
break;
|
||||
case "time":
|
||||
result = now.toTimeString().split(" ")[0]; // HH:mm:ss
|
||||
result = toLocalTime(now);
|
||||
break;
|
||||
case "datetime":
|
||||
result = now.toISOString().replace("T", " ").split(".")[0]; // YYYY-MM-DD HH:mm:ss
|
||||
result = toLocalDateTime(now);
|
||||
break;
|
||||
case "timestamp":
|
||||
result = now.getTime().toString();
|
||||
break;
|
||||
default:
|
||||
result = now.toISOString(); // ISO 8601 format
|
||||
result = toLocalDateTime(now);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5156,7 +5156,8 @@ export class ButtonActionExecutor {
|
|||
const menuName = localStorage.getItem("currentMenuName");
|
||||
if (menuName) defaultFileName = menuName;
|
||||
}
|
||||
const fileName = config.excelFileName || `${defaultFileName}_${new Date().toISOString().split("T")[0]}.xlsx`;
|
||||
const _xd = new Date();
|
||||
const fileName = config.excelFileName || `${defaultFileName}_${_xd.getFullYear()}-${String(_xd.getMonth() + 1).padStart(2, "0")}-${String(_xd.getDate()).padStart(2, "0")}.xlsx`;
|
||||
const sheetName = config.excelSheetName || "Sheet1";
|
||||
|
||||
await exportToExcel(dataToExport, fileName, sheetName, true);
|
||||
|
|
@ -5262,7 +5263,8 @@ export class ButtonActionExecutor {
|
|||
}
|
||||
}
|
||||
|
||||
const fileName = config.excelFileName || `${defaultFileName}_${new Date().toISOString().split("T")[0]}.xlsx`;
|
||||
const _xd2 = new Date();
|
||||
const fileName = config.excelFileName || `${defaultFileName}_${_xd2.getFullYear()}-${String(_xd2.getMonth() + 1).padStart(2, "0")}-${String(_xd2.getDate()).padStart(2, "0")}.xlsx`;
|
||||
const sheetName = config.excelSheetName || "Sheet1";
|
||||
const includeHeaders = config.excelIncludeHeaders !== false;
|
||||
|
||||
|
|
|
|||
|
|
@ -440,7 +440,7 @@ const validateDateField = (fieldName: string, value: any, config?: Record<string
|
|||
}
|
||||
}
|
||||
|
||||
return { isValid: true, transformedValue: dateValue.toISOString().split("T")[0] };
|
||||
return { isValid: true, transformedValue: `${dateValue.getFullYear()}-${String(dateValue.getMonth() + 1).padStart(2, "0")}-${String(dateValue.getDate()).padStart(2, "0")}` };
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -0,0 +1,30 @@
|
|||
/**
|
||||
* 로컬(한국) 시간 기준 날짜/시간 포맷 유틸리티
|
||||
* DB 타임존이 Asia/Seoul로 설정되어 있어 로컬 시간 기준으로 포맷
|
||||
*
|
||||
* toISOString()은 항상 UTC를 반환하므로 자동값 생성 시 사용 금지
|
||||
*/
|
||||
|
||||
export function toLocalDate(date: Date = new Date()): string {
|
||||
const y = date.getFullYear();
|
||||
const m = String(date.getMonth() + 1).padStart(2, "0");
|
||||
const d = String(date.getDate()).padStart(2, "0");
|
||||
return `${y}-${m}-${d}`;
|
||||
}
|
||||
|
||||
export function toLocalTime(date: Date = new Date()): string {
|
||||
const h = String(date.getHours()).padStart(2, "0");
|
||||
const min = String(date.getMinutes()).padStart(2, "0");
|
||||
const sec = String(date.getSeconds()).padStart(2, "0");
|
||||
return `${h}:${min}:${sec}`;
|
||||
}
|
||||
|
||||
export function toLocalDateTime(date: Date = new Date()): string {
|
||||
return `${toLocalDate(date)} ${toLocalTime(date)}`;
|
||||
}
|
||||
|
||||
export function toLocalDateTimeForInput(date: Date = new Date()): string {
|
||||
const h = String(date.getHours()).padStart(2, "0");
|
||||
const min = String(date.getMinutes()).padStart(2, "0");
|
||||
return `${toLocalDate(date)}T${h}:${min}`;
|
||||
}
|
||||
|
|
@ -91,8 +91,8 @@ function getDefaultPeriod(): { start: string; end: string } {
|
|||
const start = new Date(now.getFullYear(), now.getMonth(), 1);
|
||||
const end = new Date(now.getFullYear(), now.getMonth() + 1, 0);
|
||||
return {
|
||||
start: start.toISOString().split("T")[0],
|
||||
end: end.toISOString().split("T")[0],
|
||||
start: `${start.getFullYear()}-${String(start.getMonth() + 1).padStart(2, "0")}-${String(start.getDate()).padStart(2, "0")}`,
|
||||
end: `${end.getFullYear()}-${String(end.getMonth() + 1).padStart(2, "0")}-${String(end.getDate()).padStart(2, "0")}`,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue