180 lines
6.3 KiB
TypeScript
180 lines
6.3 KiB
TypeScript
"use client";
|
||
|
||
import React, { useState } from "react";
|
||
import { Monitor, Tablet, Smartphone, Settings } from "lucide-react";
|
||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
|
||
import { Input } from "@/components/ui/input";
|
||
import { Label } from "@/components/ui/label";
|
||
import { Button } from "@/components/ui/button";
|
||
import { ScreenResolution, SCREEN_RESOLUTIONS } from "@/types/screen";
|
||
|
||
interface ResolutionPanelProps {
|
||
currentResolution: ScreenResolution;
|
||
onResolutionChange: (resolution: ScreenResolution) => void;
|
||
}
|
||
|
||
const ResolutionPanel: React.FC<ResolutionPanelProps> = ({ currentResolution, onResolutionChange }) => {
|
||
const [customWidth, setCustomWidth] = useState(currentResolution.width.toString());
|
||
const [customHeight, setCustomHeight] = useState(currentResolution.height.toString());
|
||
const [selectedPreset, setSelectedPreset] = useState<string>(
|
||
SCREEN_RESOLUTIONS.find((r) => r.width === currentResolution.width && r.height === currentResolution.height)
|
||
?.name || "custom",
|
||
);
|
||
|
||
const handlePresetChange = (presetName: string) => {
|
||
setSelectedPreset(presetName);
|
||
|
||
if (presetName === "custom") {
|
||
return;
|
||
}
|
||
|
||
const preset = SCREEN_RESOLUTIONS.find((r) => r.name === presetName);
|
||
if (preset) {
|
||
setCustomWidth(preset.width.toString());
|
||
setCustomHeight(preset.height.toString());
|
||
onResolutionChange(preset);
|
||
}
|
||
};
|
||
|
||
const handleCustomResolution = () => {
|
||
const width = parseInt(customWidth);
|
||
const height = parseInt(customHeight);
|
||
|
||
if (width > 0 && height > 0) {
|
||
const customResolution: ScreenResolution = {
|
||
width,
|
||
height,
|
||
name: `사용자 정의 (${width}×${height})`,
|
||
category: "custom",
|
||
};
|
||
onResolutionChange(customResolution);
|
||
setSelectedPreset("custom");
|
||
}
|
||
};
|
||
|
||
const getCategoryIcon = (category: string) => {
|
||
switch (category) {
|
||
case "desktop":
|
||
return <Monitor className="h-4 w-4" />;
|
||
case "tablet":
|
||
return <Tablet className="h-4 w-4" />;
|
||
case "mobile":
|
||
return <Smartphone className="h-4 w-4" />;
|
||
default:
|
||
return <Settings className="h-4 w-4" />;
|
||
}
|
||
};
|
||
|
||
const getCategoryColor = (category: string) => {
|
||
switch (category) {
|
||
case "desktop":
|
||
return "text-primary";
|
||
case "tablet":
|
||
return "text-green-600";
|
||
case "mobile":
|
||
return "text-purple-600";
|
||
default:
|
||
return "text-muted-foreground";
|
||
}
|
||
};
|
||
|
||
return (
|
||
<div className="space-y-4">
|
||
{/* 프리셋 선택 */}
|
||
<div className="space-y-2">
|
||
<Label className="text-xs font-medium">해상도 프리셋</Label>
|
||
<Select value={selectedPreset} onValueChange={handlePresetChange}>
|
||
<SelectTrigger className=" text-xsh-6 w-full px-2 py-0">
|
||
<SelectValue placeholder="해상도를 선택하세요" />
|
||
</SelectTrigger>
|
||
<SelectContent>
|
||
{/* Desktop */}
|
||
<div className="px-2 py-1 text-xs font-medium text-gray-500">데스크톱</div>
|
||
{SCREEN_RESOLUTIONS.filter((r) => r.category === "desktop").map((resolution) => (
|
||
<SelectItem key={resolution.name} value={resolution.name}>
|
||
<div className="flex items-center space-x-2">
|
||
<Monitor className="text-primary h-4 w-4" />
|
||
<span>{resolution.name}</span>
|
||
</div>
|
||
</SelectItem>
|
||
))}
|
||
|
||
{/* Tablet */}
|
||
<div className="px-2 py-1 text-xs font-medium text-gray-500">태블릿</div>
|
||
{SCREEN_RESOLUTIONS.filter((r) => r.category === "tablet").map((resolution) => (
|
||
<SelectItem key={resolution.name} value={resolution.name}>
|
||
<div className="flex items-center space-x-2">
|
||
<Tablet className="h-4 w-4 text-green-600" />
|
||
<span>{resolution.name}</span>
|
||
</div>
|
||
</SelectItem>
|
||
))}
|
||
|
||
{/* Mobile */}
|
||
<div className="px-2 py-1 text-xs font-medium text-gray-500">모바일</div>
|
||
{SCREEN_RESOLUTIONS.filter((r) => r.category === "mobile").map((resolution) => (
|
||
<SelectItem key={resolution.name} value={resolution.name}>
|
||
<div className="flex items-center space-x-2">
|
||
<Smartphone className="h-4 w-4 text-purple-600" />
|
||
<span>{resolution.name}</span>
|
||
</div>
|
||
</SelectItem>
|
||
))}
|
||
|
||
{/* Custom */}
|
||
<div className="px-2 py-1 text-xs font-medium text-gray-500">사용자 정의</div>
|
||
<SelectItem value="custom">
|
||
<div className="flex items-center space-x-2">
|
||
<Settings className="text-muted-foreground h-4 w-4" />
|
||
<span>사용자 정의</span>
|
||
</div>
|
||
</SelectItem>
|
||
</SelectContent>
|
||
</Select>
|
||
</div>
|
||
|
||
{/* 사용자 정의 해상도 */}
|
||
{selectedPreset === "custom" && (
|
||
<div className="space-y-3 rounded-lg border bg-gray-50 p-3">
|
||
<Label className="text-sm font-medium">사용자 정의 해상도</Label>
|
||
<div className="grid grid-cols-2 gap-3">
|
||
<div className="space-y-1">
|
||
<Label className="text-muted-foreground text-xs">너비 (px)</Label>
|
||
<Input
|
||
type="number"
|
||
value={customWidth}
|
||
onChange={(e) => setCustomWidth(e.target.value)}
|
||
placeholder="1920"
|
||
min="1"
|
||
step="1"
|
||
className="h-6 w-full px-2 py-0 text-xs"
|
||
/>
|
||
</div>
|
||
<div className="space-y-1">
|
||
<Label className="text-muted-foreground text-xs">높이 (px)</Label>
|
||
<Input
|
||
type="number"
|
||
value={customHeight}
|
||
onChange={(e) => setCustomHeight(e.target.value)}
|
||
placeholder="1080"
|
||
min="1"
|
||
step="1"
|
||
className="h-6 w-full px-2 py-0 text-xs"
|
||
/>
|
||
</div>
|
||
</div>
|
||
<Button
|
||
onClick={handleCustomResolution}
|
||
size="sm"
|
||
className="h-6 w-full px-2 py-0 text-xs"
|
||
>
|
||
적용
|
||
</Button>
|
||
</div>
|
||
)}
|
||
</div>
|
||
);
|
||
};
|
||
|
||
export default ResolutionPanel;
|