mirror of
https://github.com/maziggy/bambuddy.git
synced 2026-10-01 03:31:25 +02:00
Improved printer card size selector
This commit is contained in:
@@ -23,8 +23,6 @@ import {
|
||||
Pencil,
|
||||
ArrowUp,
|
||||
ArrowDown,
|
||||
LayoutGrid,
|
||||
LayoutList,
|
||||
Layers,
|
||||
Video,
|
||||
Search,
|
||||
@@ -37,7 +35,6 @@ import {
|
||||
Fan,
|
||||
Wind,
|
||||
AirVent,
|
||||
Minus,
|
||||
Download,
|
||||
} from 'lucide-react';
|
||||
|
||||
@@ -862,6 +859,7 @@ function PrinterCard({
|
||||
hideIfDisconnected,
|
||||
maintenanceInfo,
|
||||
viewMode = 'expanded',
|
||||
cardSize = 2,
|
||||
amsThresholds,
|
||||
spoolmanEnabled = false,
|
||||
hasUnlinkedSpools = false,
|
||||
@@ -870,6 +868,7 @@ function PrinterCard({
|
||||
hideIfDisconnected?: boolean;
|
||||
maintenanceInfo?: PrinterMaintenanceInfo;
|
||||
viewMode?: ViewMode;
|
||||
cardSize?: number;
|
||||
amsThresholds?: {
|
||||
humidityGood: number;
|
||||
humidityFair: number;
|
||||
@@ -1209,11 +1208,40 @@ function PrinterCard({
|
||||
return null;
|
||||
}
|
||||
|
||||
// Size-based styling helpers
|
||||
const getImageSize = () => {
|
||||
switch (cardSize) {
|
||||
case 1: return 'w-10 h-10';
|
||||
case 2: return 'w-14 h-14';
|
||||
case 3: return 'w-16 h-16';
|
||||
case 4: return 'w-20 h-20';
|
||||
default: return 'w-14 h-14';
|
||||
}
|
||||
};
|
||||
const getTitleSize = () => {
|
||||
switch (cardSize) {
|
||||
case 1: return 'text-base truncate';
|
||||
case 2: return 'text-lg';
|
||||
case 3: return 'text-xl';
|
||||
case 4: return 'text-2xl';
|
||||
default: return 'text-lg';
|
||||
}
|
||||
};
|
||||
const getSpacing = () => {
|
||||
switch (cardSize) {
|
||||
case 1: return 'mb-2';
|
||||
case 2: return 'mb-4';
|
||||
case 3: return 'mb-5';
|
||||
case 4: return 'mb-6';
|
||||
default: return 'mb-4';
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Card className="relative">
|
||||
<CardContent>
|
||||
<CardContent className={cardSize >= 3 ? 'p-5' : ''}>
|
||||
{/* Header */}
|
||||
<div className={viewMode === 'compact' ? 'mb-2' : 'mb-4'}>
|
||||
<div className={getSpacing()}>
|
||||
{/* Top row: Image, Name, Menu */}
|
||||
<div className="flex items-start justify-between gap-2">
|
||||
<div className="flex items-center gap-3 min-w-0 flex-1">
|
||||
@@ -1221,11 +1249,11 @@ function PrinterCard({
|
||||
<img
|
||||
src={getPrinterImage(printer.model)}
|
||||
alt={printer.model || 'Printer'}
|
||||
className={`object-contain rounded-lg bg-bambu-dark flex-shrink-0 ${viewMode === 'compact' ? 'w-10 h-10' : 'w-14 h-14'}`}
|
||||
className={`object-contain rounded-lg bg-bambu-dark flex-shrink-0 ${getImageSize()}`}
|
||||
/>
|
||||
<div className="min-w-0 flex-1">
|
||||
<div className="flex items-center gap-2">
|
||||
<h3 className={`font-semibold text-white ${viewMode === 'compact' ? 'text-base truncate' : 'text-lg'}`}>{printer.name}</h3>
|
||||
<h3 className={`font-semibold text-white ${getTitleSize()}`}>{printer.name}</h3>
|
||||
{/* Connection indicator dot for compact mode */}
|
||||
{viewMode === 'compact' && (
|
||||
<div
|
||||
@@ -3568,14 +3596,13 @@ export function PrintersPage() {
|
||||
const [sortAsc, setSortAsc] = useState<boolean>(() => {
|
||||
return localStorage.getItem('printerSortAsc') !== 'false';
|
||||
});
|
||||
const [viewMode, setViewMode] = useState<ViewMode>(() => {
|
||||
return (localStorage.getItem('printerViewMode') as ViewMode) || 'expanded';
|
||||
});
|
||||
// Card size: 1=small, 2=medium, 3=large, 4=xl
|
||||
const [cardSize, setCardSize] = useState<number>(() => {
|
||||
const saved = localStorage.getItem('printerCardSize');
|
||||
return saved ? parseInt(saved, 10) : 2; // Default to medium
|
||||
});
|
||||
// Derive viewMode from cardSize: S=compact, M/L/XL=expanded
|
||||
const viewMode: ViewMode = cardSize === 1 ? 'compact' : 'expanded';
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
const { data: printers, isLoading } = useQuery({
|
||||
@@ -3679,26 +3706,14 @@ export function PrintersPage() {
|
||||
localStorage.setItem('printerSortAsc', String(newAsc));
|
||||
};
|
||||
|
||||
const toggleViewMode = () => {
|
||||
const newMode = viewMode === 'expanded' ? 'compact' : 'expanded';
|
||||
setViewMode(newMode);
|
||||
localStorage.setItem('printerViewMode', newMode);
|
||||
};
|
||||
|
||||
const changeCardSize = (delta: number) => {
|
||||
const newSize = Math.max(1, Math.min(4, cardSize + delta));
|
||||
setCardSize(newSize);
|
||||
localStorage.setItem('printerCardSize', String(newSize));
|
||||
};
|
||||
|
||||
// Grid classes based on card size (1=small, 2=medium, 3=large, 4=xl)
|
||||
const getGridClasses = () => {
|
||||
switch (cardSize) {
|
||||
case 1: return 'grid-cols-2 md:grid-cols-3 lg:grid-cols-4 xl:grid-cols-5';
|
||||
case 2: return 'grid-cols-1 md:grid-cols-2 lg:grid-cols-3';
|
||||
case 3: return 'grid-cols-1 md:grid-cols-2';
|
||||
case 4: return 'grid-cols-1 max-w-3xl';
|
||||
default: return 'grid-cols-1 md:grid-cols-2 lg:grid-cols-3';
|
||||
case 1: return 'grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 xl:grid-cols-5'; // S: many small cards
|
||||
case 2: return 'grid-cols-1 md:grid-cols-2 xl:grid-cols-3'; // M: medium cards
|
||||
case 3: return 'grid-cols-1 lg:grid-cols-2'; // L: large cards, 2 columns max
|
||||
case 4: return 'grid-cols-1'; // XL: single column, full width
|
||||
default: return 'grid-cols-1 md:grid-cols-2 xl:grid-cols-3';
|
||||
}
|
||||
};
|
||||
|
||||
@@ -3797,40 +3812,33 @@ export function PrintersPage() {
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* View mode toggle */}
|
||||
<button
|
||||
onClick={toggleViewMode}
|
||||
className="p-1.5 rounded-lg hover:bg-bambu-dark-tertiary transition-colors"
|
||||
title={viewMode === 'expanded' ? 'Switch to compact view' : 'Switch to expanded view'}
|
||||
>
|
||||
{viewMode === 'expanded' ? (
|
||||
<LayoutList className="w-5 h-5 text-bambu-gray" />
|
||||
) : (
|
||||
<LayoutGrid className="w-5 h-5 text-bambu-gray" />
|
||||
)}
|
||||
</button>
|
||||
|
||||
{/* Card size control */}
|
||||
<div className="flex items-center gap-1 bg-bambu-dark rounded-lg border border-bambu-dark-tertiary">
|
||||
<button
|
||||
onClick={() => changeCardSize(-1)}
|
||||
disabled={cardSize <= 1}
|
||||
className="p-1.5 rounded-l-lg hover:bg-bambu-dark-tertiary transition-colors disabled:opacity-30 disabled:cursor-not-allowed"
|
||||
title="Smaller cards"
|
||||
>
|
||||
<Minus className="w-4 h-4 text-bambu-gray" />
|
||||
</button>
|
||||
<span className="text-xs text-bambu-gray w-6 text-center font-medium">
|
||||
{cardSizeLabels[cardSize - 1]}
|
||||
</span>
|
||||
<button
|
||||
onClick={() => changeCardSize(1)}
|
||||
disabled={cardSize >= 4}
|
||||
className="p-1.5 rounded-r-lg hover:bg-bambu-dark-tertiary transition-colors disabled:opacity-30 disabled:cursor-not-allowed"
|
||||
title="Larger cards"
|
||||
>
|
||||
<Plus className="w-4 h-4 text-bambu-gray" />
|
||||
</button>
|
||||
{/* Card size selector */}
|
||||
<div className="flex items-center bg-bambu-dark rounded-lg border border-bambu-dark-tertiary">
|
||||
{cardSizeLabels.map((label, index) => {
|
||||
const size = index + 1;
|
||||
const isSelected = cardSize === size;
|
||||
return (
|
||||
<button
|
||||
key={label}
|
||||
onClick={() => {
|
||||
setCardSize(size);
|
||||
localStorage.setItem('printerCardSize', String(size));
|
||||
}}
|
||||
className={`px-2 py-1.5 text-xs font-medium transition-colors ${
|
||||
index === 0 ? 'rounded-l-lg' : ''
|
||||
} ${
|
||||
index === cardSizeLabels.length - 1 ? 'rounded-r-lg' : ''
|
||||
} ${
|
||||
isSelected
|
||||
? 'bg-bambu-green text-white'
|
||||
: 'text-bambu-gray hover:bg-bambu-dark-tertiary hover:text-white'
|
||||
}`}
|
||||
title={`${label === 'S' ? 'Small' : label === 'M' ? 'Medium' : label === 'L' ? 'Large' : 'Extra large'} cards`}
|
||||
>
|
||||
{label}
|
||||
</button>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
|
||||
<div className="w-px h-6 bg-bambu-dark-tertiary" />
|
||||
@@ -3925,6 +3933,7 @@ export function PrintersPage() {
|
||||
hideIfDisconnected={hideDisconnected}
|
||||
maintenanceInfo={maintenanceByPrinter[printer.id]}
|
||||
viewMode={viewMode}
|
||||
cardSize={cardSize}
|
||||
amsThresholds={settings ? {
|
||||
humidityGood: Number(settings.ams_humidity_good) || 40,
|
||||
humidityFair: Number(settings.ams_humidity_fair) || 60,
|
||||
@@ -3949,6 +3958,7 @@ export function PrintersPage() {
|
||||
hideIfDisconnected={hideDisconnected}
|
||||
maintenanceInfo={maintenanceByPrinter[printer.id]}
|
||||
viewMode={viewMode}
|
||||
cardSize={cardSize}
|
||||
spoolmanEnabled={spoolmanEnabled}
|
||||
hasUnlinkedSpools={hasUnlinkedSpools}
|
||||
amsThresholds={settings ? {
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+2
-2
@@ -23,8 +23,8 @@
|
||||
|
||||
<!-- Splash screens for iOS -->
|
||||
<link rel="apple-touch-startup-image" href="/img/android-chrome-512x512.png" />
|
||||
<script type="module" crossorigin src="/assets/index-DPwHFDrf.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="/assets/index-DYSmHndB.css">
|
||||
<script type="module" crossorigin src="/assets/index-BqcFmQ1s.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="/assets/index-DgCUmTZF.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
|
||||
Reference in New Issue
Block a user