전체 화면 영역 배경색을 흰색으로 통일

- 화면 이외 영역의 회색 배경(bg-gray-50)을 흰색(bg-white)으로 변경
- AppLayout의 전체 배경색을 흰색으로 변경
- 빈 화면일 때의 배경색도 흰색으로 통일
- 화면 전체가 일관된 흰색 배경으로 표시되도록 개선
This commit is contained in:
kjs 2025-09-23 15:30:02 +09:00
parent f0a9c50ca1
commit c557fc5d56
2 changed files with 189 additions and 189 deletions

View File

@ -147,7 +147,7 @@ export default function ScreenViewPage() {
const screenHeight = layout?.screenResolution?.height || 800; const screenHeight = layout?.screenResolution?.height || 800;
return ( return (
<div className="h-full w-full overflow-auto bg-gray-50"> <div className="h-full w-full overflow-auto bg-white">
{layout && layout.components.length > 0 ? ( {layout && layout.components.length > 0 ? (
// 캔버스 컴포넌트들을 정확한 해상도로 표시 // 캔버스 컴포넌트들을 정확한 해상도로 표시
<div <div
@ -160,212 +160,212 @@ export default function ScreenViewPage() {
margin: "0", // mx-auto 제거하여 사이드바 오프셋 방지 margin: "0", // mx-auto 제거하여 사이드바 오프셋 방지
}} }}
> >
{layout.components {layout.components
.filter((comp) => !comp.parentId) // 최상위 컴포넌트만 렌더링 (그룹 포함) .filter((comp) => !comp.parentId) // 최상위 컴포넌트만 렌더링 (그룹 포함)
.map((component) => { .map((component) => {
// 그룹 컴포넌트인 경우 특별 처리 // 그룹 컴포넌트인 경우 특별 처리
if (component.type === "group") { if (component.type === "group") {
const groupChildren = layout.components.filter((child) => child.parentId === component.id); const groupChildren = layout.components.filter((child) => child.parentId === component.id);
return (
<div
key={component.id}
style={{
position: "absolute",
left: `${component.position.x}px`,
top: `${component.position.y}px`,
width: `${component.size.width}px`,
height: `${component.size.height}px`,
zIndex: component.position.z || 1,
backgroundColor: (component as any).backgroundColor || "rgba(59, 130, 246, 0.1)",
border: (component as any).border || "2px dashed #3b82f6",
borderRadius: (component as any).borderRadius || "8px",
padding: "16px",
}}
>
{/* 그룹 제목 */}
{(component as any).title && (
<div className="mb-2 text-sm font-medium text-blue-700">{(component as any).title}</div>
)}
{/* 그룹 내 자식 컴포넌트들 렌더링 */}
{groupChildren.map((child) => (
<div
key={child.id}
style={{
position: "absolute",
left: `${child.position.x}px`,
top: `${child.position.y}px`,
width: `${child.size.width}px`,
height: `${child.size.height}px`,
zIndex: child.position.z || 1,
}}
>
<InteractiveScreenViewer
component={child}
allComponents={layout.components}
formData={formData}
onFormDataChange={(fieldName, value) => {
console.log("📝 폼 데이터 변경:", { fieldName, value });
setFormData((prev) => {
const newFormData = {
...prev,
[fieldName]: value,
};
console.log("📊 전체 폼 데이터:", newFormData);
return newFormData;
});
}}
screenInfo={{
id: screenId,
tableName: screen?.tableName,
}}
/>
</div>
))}
</div>
);
}
// 라벨 표시 여부 계산
const templateTypes = ["datatable"];
const shouldShowLabel =
component.style?.labelDisplay !== false &&
(component.label || component.style?.labelText) &&
!templateTypes.includes(component.type);
const labelText = component.style?.labelText || component.label || "";
const labelStyle = {
fontSize: component.style?.labelFontSize || "14px",
color: component.style?.labelColor || "#374151",
fontWeight: component.style?.labelFontWeight || "500",
backgroundColor: component.style?.labelBackgroundColor || "transparent",
padding: component.style?.labelPadding || "0",
borderRadius: component.style?.labelBorderRadius || "0",
marginBottom: component.style?.labelMarginBottom || "4px",
};
// 일반 컴포넌트 렌더링
return ( return (
<div key={component.id}> <div
{/* 라벨을 외부에 별도로 렌더링 */} key={component.id}
{shouldShowLabel && ( style={{
<div position: "absolute",
style={{ left: `${component.position.x}px`,
position: "absolute", top: `${component.position.y}px`,
left: `${component.position.x}px`, width: `${component.size.width}px`,
top: `${component.position.y - 25}px`, // 컴포넌트 위쪽에 라벨 배치 height: `${component.size.height}px`,
zIndex: (component.position.z || 1) + 1, zIndex: component.position.z || 1,
...labelStyle, backgroundColor: (component as any).backgroundColor || "rgba(59, 130, 246, 0.1)",
}} border: (component as any).border || "2px dashed #3b82f6",
> borderRadius: (component as any).borderRadius || "8px",
{labelText} padding: "16px",
{component.required && <span style={{ color: "#f97316", marginLeft: "2px" }}>*</span>} }}
</div> >
{/* 그룹 제목 */}
{(component as any).title && (
<div className="mb-2 text-sm font-medium text-blue-700">{(component as any).title}</div>
)} )}
{/* 실제 컴포넌트 */} {/* 그룹 내 자식 컴포넌트들 렌더링 */}
{groupChildren.map((child) => (
<div
key={child.id}
style={{
position: "absolute",
left: `${child.position.x}px`,
top: `${child.position.y}px`,
width: `${child.size.width}px`,
height: `${child.size.height}px`,
zIndex: child.position.z || 1,
}}
>
<InteractiveScreenViewer
component={child}
allComponents={layout.components}
formData={formData}
onFormDataChange={(fieldName, value) => {
console.log("📝 폼 데이터 변경:", { fieldName, value });
setFormData((prev) => {
const newFormData = {
...prev,
[fieldName]: value,
};
console.log("📊 전체 폼 데이터:", newFormData);
return newFormData;
});
}}
screenInfo={{
id: screenId,
tableName: screen?.tableName,
}}
/>
</div>
))}
</div>
);
}
// 라벨 표시 여부 계산
const templateTypes = ["datatable"];
const shouldShowLabel =
component.style?.labelDisplay !== false &&
(component.label || component.style?.labelText) &&
!templateTypes.includes(component.type);
const labelText = component.style?.labelText || component.label || "";
const labelStyle = {
fontSize: component.style?.labelFontSize || "14px",
color: component.style?.labelColor || "#374151",
fontWeight: component.style?.labelFontWeight || "500",
backgroundColor: component.style?.labelBackgroundColor || "transparent",
padding: component.style?.labelPadding || "0",
borderRadius: component.style?.labelBorderRadius || "0",
marginBottom: component.style?.labelMarginBottom || "4px",
};
// 일반 컴포넌트 렌더링
return (
<div key={component.id}>
{/* 라벨을 외부에 별도로 렌더링 */}
{shouldShowLabel && (
<div <div
style={{ style={{
position: "absolute", position: "absolute",
left: `${component.position.x}px`, left: `${component.position.x}px`,
top: `${component.position.y}px`, top: `${component.position.y - 25}px`, // 컴포넌트 위쪽에 라벨 배치
width: `${component.size.width}px`, zIndex: (component.position.z || 1) + 1,
height: `${component.size.height}px`, ...labelStyle,
zIndex: component.position.z || 1,
}}
onMouseEnter={() => {
console.log("🎯 할당된 화면 컴포넌트:", {
id: component.id,
type: component.type,
position: component.position,
size: component.size,
styleWidth: component.style?.width,
styleHeight: component.style?.height,
finalWidth: `${component.size.width}px`,
finalHeight: `${component.size.height}px`,
});
}} }}
> >
{/* 위젯 컴포넌트가 아닌 경우 DynamicComponentRenderer 사용 */} {labelText}
{component.type !== "widget" ? ( {component.required && <span style={{ color: "#f97316", marginLeft: "2px" }}>*</span>}
<DynamicComponentRenderer </div>
component={component} )}
isInteractive={true}
formData={formData} {/* 실제 컴포넌트 */}
onFormDataChange={(fieldName, value) => { <div
style={{
position: "absolute",
left: `${component.position.x}px`,
top: `${component.position.y}px`,
width: `${component.size.width}px`,
height: `${component.size.height}px`,
zIndex: component.position.z || 1,
}}
onMouseEnter={() => {
console.log("🎯 할당된 화면 컴포넌트:", {
id: component.id,
type: component.type,
position: component.position,
size: component.size,
styleWidth: component.style?.width,
styleHeight: component.style?.height,
finalWidth: `${component.size.width}px`,
finalHeight: `${component.size.height}px`,
});
}}
>
{/* 위젯 컴포넌트가 아닌 경우 DynamicComponentRenderer 사용 */}
{component.type !== "widget" ? (
<DynamicComponentRenderer
component={component}
isInteractive={true}
formData={formData}
onFormDataChange={(fieldName, value) => {
setFormData((prev) => ({
...prev,
[fieldName]: value,
}));
}}
screenId={screenId}
tableName={screen?.tableName}
onRefresh={() => {
console.log("화면 새로고침 요청");
// 테이블 컴포넌트 강제 새로고침을 위한 키 업데이트
setRefreshKey((prev) => prev + 1);
// 선택된 행 상태도 초기화
setSelectedRows([]);
setSelectedRowsData([]);
}}
onClose={() => {
console.log("화면 닫기 요청");
}}
// 테이블 선택된 행 정보 전달
selectedRows={selectedRows}
selectedRowsData={selectedRowsData}
onSelectedRowsChange={(newSelectedRows, newSelectedRowsData) => {
setSelectedRows(newSelectedRows);
setSelectedRowsData(newSelectedRowsData);
}}
// 테이블 새로고침 키 전달
refreshKey={refreshKey}
/>
) : (
<DynamicWebTypeRenderer
webType={component.webType || "text"}
config={component.webTypeConfig}
props={{
component: component,
value: formData[component.columnName || component.id] || "",
onChange: (value: any) => {
const fieldName = component.columnName || component.id;
setFormData((prev) => ({ setFormData((prev) => ({
...prev, ...prev,
[fieldName]: value, [fieldName]: value,
})); }));
}} },
screenId={screenId} onFormDataChange: (fieldName, value) => {
tableName={screen?.tableName} console.log(`🎯 page.tsx onFormDataChange 호출: ${fieldName} = "${value}"`);
onRefresh={() => { console.log(`📋 현재 formData:`, formData);
console.log("화면 새로고침 요청"); setFormData((prev) => {
// 테이블 컴포넌트 강제 새로고침을 위한 키 업데이트 const newFormData = {
setRefreshKey((prev) => prev + 1);
// 선택된 행 상태도 초기화
setSelectedRows([]);
setSelectedRowsData([]);
}}
onClose={() => {
console.log("화면 닫기 요청");
}}
// 테이블 선택된 행 정보 전달
selectedRows={selectedRows}
selectedRowsData={selectedRowsData}
onSelectedRowsChange={(newSelectedRows, newSelectedRowsData) => {
setSelectedRows(newSelectedRows);
setSelectedRowsData(newSelectedRowsData);
}}
// 테이블 새로고침 키 전달
refreshKey={refreshKey}
/>
) : (
<DynamicWebTypeRenderer
webType={component.webType || "text"}
config={component.webTypeConfig}
props={{
component: component,
value: formData[component.columnName || component.id] || "",
onChange: (value: any) => {
const fieldName = component.columnName || component.id;
setFormData((prev) => ({
...prev, ...prev,
[fieldName]: value, [fieldName]: value,
})); };
}, console.log(`📝 업데이트된 formData:`, newFormData);
onFormDataChange: (fieldName, value) => { return newFormData;
console.log(`🎯 page.tsx onFormDataChange 호출: ${fieldName} = "${value}"`); });
console.log(`📋 현재 formData:`, formData); },
setFormData((prev) => { isInteractive: true,
const newFormData = { formData: formData,
...prev, readonly: component.readonly,
[fieldName]: value, required: component.required,
}; placeholder: component.placeholder,
console.log(`📝 업데이트된 formData:`, newFormData); className: "w-full h-full",
return newFormData; }}
}); />
}, )}
isInteractive: true,
formData: formData,
readonly: component.readonly,
required: component.required,
placeholder: component.placeholder,
className: "w-full h-full",
}}
/>
)}
</div>
</div> </div>
); </div>
})} );
</div> })}
</div>
) : ( ) : (
// 빈 화면일 때도 깔끔하게 표시 // 빈 화면일 때도 깔끔하게 표시
<div <div
className="mx-auto flex items-center justify-center bg-gray-50" className="mx-auto flex items-center justify-center bg-white"
style={{ style={{
width: `${screenWidth}px`, width: `${screenWidth}px`,
height: `${screenHeight}px`, height: `${screenHeight}px`,

View File

@ -357,7 +357,7 @@ function AppLayoutInner({ children }: AppLayoutProps) {
const uiMenus = convertMenuToUI(currentMenus, user as ExtendedUserInfo); const uiMenus = convertMenuToUI(currentMenus, user as ExtendedUserInfo);
return ( return (
<div className="flex h-screen flex-col bg-slate-50"> <div className="flex h-screen flex-col bg-white">
{/* MainHeader 컴포넌트 사용 */} {/* MainHeader 컴포넌트 사용 */}
<MainHeader <MainHeader
user={user} user={user}
@ -420,7 +420,7 @@ function AppLayoutInner({ children }: AppLayoutProps) {
</aside> </aside>
{/* 가운데 컨텐츠 영역 */} {/* 가운데 컨텐츠 영역 */}
<main className="bg-background flex-1">{children}</main> <main className="flex-1 bg-white">{children}</main>
</div> </div>
{/* 프로필 수정 모달 */} {/* 프로필 수정 모달 */}