feat: implement smart factory log transmission and enhance rack structure patterns

- Added a new utility function `sendSmartFactoryLog` to transmit user access logs to the smart factory logging service upon successful login, ensuring non-blocking behavior.
- Integrated the smart factory log transmission into the `AuthController` to log user access asynchronously.
- Introduced pattern utilities for generating location codes and names based on configurable patterns in the rack structure components, improving flexibility and maintainability.
- Enhanced the `RackStructureConfigPanel` to allow users to define custom patterns for location codes and names, with real-time previews and a list of available variables.

Made-with: Cursor
This commit is contained in:
kjs
2026-03-11 18:34:58 +09:00
parent 000484349b
commit 41d58cbb62
8 changed files with 396 additions and 27 deletions

View File

@@ -1,6 +1,6 @@
"use client";
import React, { useState, useEffect } from "react";
import React, { useState, useEffect, useMemo } from "react";
import { Label } from "@/components/ui/label";
import { Input } from "@/components/ui/input";
import { Switch } from "@/components/ui/switch";
@@ -12,6 +12,47 @@ import {
SelectValue,
} from "@/components/ui/select";
import { RackStructureComponentConfig, FieldMapping } from "./types";
import { applyLocationPattern, DEFAULT_CODE_PATTERN, DEFAULT_NAME_PATTERN, PATTERN_VARIABLES } from "./patternUtils";
// 패턴 미리보기 서브 컴포넌트
const PatternPreview: React.FC<{
codePattern?: string;
namePattern?: string;
}> = ({ codePattern, namePattern }) => {
const sampleVars = {
warehouse: "WH002",
warehouseName: "2창고",
floor: "2층",
zone: "A구역",
row: 1,
level: 3,
};
const previewCode = useMemo(
() => applyLocationPattern(codePattern || DEFAULT_CODE_PATTERN, sampleVars),
[codePattern],
);
const previewName = useMemo(
() => applyLocationPattern(namePattern || DEFAULT_NAME_PATTERN, sampleVars),
[namePattern],
);
return (
<div className="rounded-md border border-primary/20 bg-primary/5 p-2.5">
<div className="mb-1.5 text-[10px] font-medium text-primary"> (2 / 2 / A구역 / 1 / 3)</div>
<div className="space-y-1">
<div className="flex items-center gap-2 text-xs">
<span className="w-14 shrink-0 text-muted-foreground">:</span>
<code className="rounded bg-background px-1.5 py-0.5 font-mono text-foreground">{previewCode}</code>
</div>
<div className="flex items-center gap-2 text-xs">
<span className="w-14 shrink-0 text-muted-foreground">:</span>
<code className="rounded bg-background px-1.5 py-0.5 font-mono text-foreground">{previewName}</code>
</div>
</div>
</div>
);
};
interface RackStructureConfigPanelProps {
config: RackStructureComponentConfig;
@@ -205,6 +246,61 @@ export const RackStructureConfigPanel: React.FC<RackStructureConfigPanelProps> =
</div>
</div>
{/* 위치코드 패턴 설정 */}
<div className="space-y-3 border-t pt-3">
<div className="text-sm font-medium text-foreground">/ </div>
<p className="text-xs text-muted-foreground">
</p>
{/* 위치코드 패턴 */}
<div>
<Label className="text-xs"> </Label>
<Input
value={config.codePattern || ""}
onChange={(e) => handleChange("codePattern", e.target.value || undefined)}
placeholder="{warehouse}-{floor}{zone}-{row:02}-{level}"
className="h-8 font-mono text-xs"
/>
<p className="mt-1 text-[10px] text-muted-foreground">
: {"{warehouse}-{floor}{zone}-{row:02}-{level}"}
</p>
</div>
{/* 위치명 패턴 */}
<div>
<Label className="text-xs"> </Label>
<Input
value={config.namePattern || ""}
onChange={(e) => handleChange("namePattern", e.target.value || undefined)}
placeholder="{zone}-{row:02}열-{level}단"
className="h-8 font-mono text-xs"
/>
<p className="mt-1 text-[10px] text-muted-foreground">
: {"{zone}-{row:02}열-{level}단"}
</p>
</div>
{/* 실시간 미리보기 */}
<PatternPreview
codePattern={config.codePattern}
namePattern={config.namePattern}
/>
{/* 사용 가능한 변수 목록 */}
<div className="rounded-md border bg-muted/50 p-2">
<div className="mb-1 text-[10px] font-medium text-foreground"> </div>
<div className="grid grid-cols-2 gap-x-3 gap-y-0.5">
{PATTERN_VARIABLES.map((v) => (
<div key={v.token} className="flex items-center gap-1 text-[10px]">
<code className="rounded bg-primary/10 px-1 font-mono text-primary">{v.token}</code>
<span className="text-muted-foreground">{v.description}</span>
</div>
))}
</div>
</div>
</div>
{/* 제한 설정 */}
<div className="space-y-3 border-t pt-3">
<div className="text-sm font-medium text-foreground"> </div>