Add scroll area to widget settings modal
Some checks failed
Build Frontend / build (push) Failing after 6s
Some checks failed
Build Frontend / build (push) Failing after 6s
Wrapped the widget settings modal content in a ScrollArea to improve usability when there are many settings, preventing overflow and keeping the modal compact.
This commit is contained in:
@@ -22,6 +22,7 @@ import {
|
|||||||
} from "@/components/ui/select"
|
} from "@/components/ui/select"
|
||||||
import { WidgetConfig } from "@/hooks/useWidgetLayout"
|
import { WidgetConfig } from "@/hooks/useWidgetLayout"
|
||||||
import { Settings2 } from "lucide-react"
|
import { Settings2 } from "lucide-react"
|
||||||
|
import { ScrollArea } from "@/components/ui/scroll-area"
|
||||||
|
|
||||||
interface WidgetSettingsModalProps {
|
interface WidgetSettingsModalProps {
|
||||||
widget: WidgetConfig | null
|
widget: WidgetConfig | null
|
||||||
@@ -69,213 +70,215 @@ export function WidgetSettingsModal({ widget, open, onOpenChange, onSave }: Widg
|
|||||||
</DialogDescription>
|
</DialogDescription>
|
||||||
</DialogHeader>
|
</DialogHeader>
|
||||||
|
|
||||||
<div className="space-y-6 py-4">
|
<ScrollArea className="max-h-[60vh] -mr-4 pr-4">
|
||||||
{/* Resize Selection */}
|
<div className="space-y-6 py-4">
|
||||||
<div className="space-y-3 pb-6 border-b border-border/40">
|
{/* Resize Selection */}
|
||||||
<Label className="text-xs font-semibold text-muted-foreground uppercase tracking-wider">Widget Display</Label>
|
<div className="space-y-3 pb-6 border-b border-border/40">
|
||||||
<div className="flex items-center justify-between">
|
<Label className="text-xs font-semibold text-muted-foreground uppercase tracking-wider">Widget Display</Label>
|
||||||
<Label htmlFor="colSpan" className="text-sm font-medium">Widget Width</Label>
|
<div className="flex items-center justify-between">
|
||||||
<Select
|
<Label htmlFor="colSpan" className="text-sm font-medium">Widget Width</Label>
|
||||||
value={String(localColSpan)}
|
<Select
|
||||||
onValueChange={(v) => setLocalColSpan(parseInt(v))}
|
value={String(localColSpan)}
|
||||||
>
|
onValueChange={(v) => setLocalColSpan(parseInt(v))}
|
||||||
<SelectTrigger className="w-40">
|
>
|
||||||
<SelectValue />
|
<SelectTrigger className="w-40">
|
||||||
</SelectTrigger>
|
<SelectValue />
|
||||||
<SelectContent>
|
</SelectTrigger>
|
||||||
<SelectItem value="1">Small (1/4)</SelectItem>
|
<SelectContent>
|
||||||
<SelectItem value="2">Medium (1/2)</SelectItem>
|
<SelectItem value="1">Small (1/4)</SelectItem>
|
||||||
<SelectItem value="3">Large (3/4)</SelectItem>
|
<SelectItem value="2">Medium (1/2)</SelectItem>
|
||||||
<SelectItem value="4">Full Width</SelectItem>
|
<SelectItem value="3">Large (3/4)</SelectItem>
|
||||||
</SelectContent>
|
<SelectItem value="4">Full Width</SelectItem>
|
||||||
</Select>
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="space-y-4">
|
||||||
|
{/* Recent Activity Settings */}
|
||||||
|
{widget.id === "recent-activity" && (
|
||||||
|
<div className="space-y-4">
|
||||||
|
<div className="flex items-center justify-between">
|
||||||
|
<Label htmlFor="itemCount">Number of items</Label>
|
||||||
|
<Select
|
||||||
|
value={String(localSettings.itemCount || 10)}
|
||||||
|
onValueChange={(v) => updateSetting("itemCount", parseInt(v))}
|
||||||
|
>
|
||||||
|
<SelectTrigger className="w-24">
|
||||||
|
<SelectValue />
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
<SelectItem value="5">5</SelectItem>
|
||||||
|
<SelectItem value="10">10</SelectItem>
|
||||||
|
<SelectItem value="15">15</SelectItem>
|
||||||
|
<SelectItem value="20">20</SelectItem>
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* Top Products Settings */}
|
||||||
|
{widget.id === "top-products" && (
|
||||||
|
<div className="space-y-4">
|
||||||
|
<div className="flex items-center justify-between">
|
||||||
|
<Label htmlFor="itemCount">Number of products</Label>
|
||||||
|
<Select
|
||||||
|
value={String(localSettings.itemCount || 5)}
|
||||||
|
onValueChange={(v) => updateSetting("itemCount", parseInt(v))}
|
||||||
|
>
|
||||||
|
<SelectTrigger className="w-24">
|
||||||
|
<SelectValue />
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
<SelectItem value="3">3</SelectItem>
|
||||||
|
<SelectItem value="5">5</SelectItem>
|
||||||
|
<SelectItem value="10">10</SelectItem>
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
</div>
|
||||||
|
<div className="flex items-center justify-between">
|
||||||
|
<Label htmlFor="showRevenue">Show revenue</Label>
|
||||||
|
<Switch
|
||||||
|
id="showRevenue"
|
||||||
|
checked={localSettings.showRevenue ?? true}
|
||||||
|
onCheckedChange={(checked) => updateSetting("showRevenue", checked)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* Revenue Chart Settings */}
|
||||||
|
{widget.id === "revenue-chart" && (
|
||||||
|
<div className="space-y-4">
|
||||||
|
<div className="flex items-center justify-between">
|
||||||
|
<Label htmlFor="days">Time period</Label>
|
||||||
|
<Select
|
||||||
|
value={String(localSettings.days || 7)}
|
||||||
|
onValueChange={(v) => updateSetting("days", parseInt(v))}
|
||||||
|
>
|
||||||
|
<SelectTrigger className="w-32">
|
||||||
|
<SelectValue />
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
<SelectItem value="7">Last 7 days</SelectItem>
|
||||||
|
<SelectItem value="14">Last 14 days</SelectItem>
|
||||||
|
<SelectItem value="30">Last 30 days</SelectItem>
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
</div>
|
||||||
|
<div className="flex items-center justify-between">
|
||||||
|
<Label htmlFor="showComparison">Show comparison</Label>
|
||||||
|
<Switch
|
||||||
|
id="showComparison"
|
||||||
|
checked={localSettings.showComparison ?? false}
|
||||||
|
onCheckedChange={(checked) => updateSetting("showComparison", checked)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* Low Stock Settings */}
|
||||||
|
{widget.id === "low-stock" && (
|
||||||
|
<div className="space-y-4">
|
||||||
|
<div className="flex items-center justify-between">
|
||||||
|
<Label htmlFor="threshold">Stock threshold</Label>
|
||||||
|
<Input
|
||||||
|
id="threshold"
|
||||||
|
type="number"
|
||||||
|
className="w-24"
|
||||||
|
value={localSettings.threshold || 5}
|
||||||
|
onChange={(e) => updateSetting("threshold", parseInt(e.target.value) || 5)}
|
||||||
|
min={1}
|
||||||
|
max={100}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="flex items-center justify-between">
|
||||||
|
<Label htmlFor="itemCount">Max items to show</Label>
|
||||||
|
<Select
|
||||||
|
value={String(localSettings.itemCount || 5)}
|
||||||
|
onValueChange={(v) => updateSetting("itemCount", parseInt(v))}
|
||||||
|
>
|
||||||
|
<SelectTrigger className="w-24">
|
||||||
|
<SelectValue />
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
<SelectItem value="3">3</SelectItem>
|
||||||
|
<SelectItem value="5">5</SelectItem>
|
||||||
|
<SelectItem value="10">10</SelectItem>
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* Recent Customers Settings */}
|
||||||
|
{widget.id === "recent-customers" && (
|
||||||
|
<div className="space-y-4">
|
||||||
|
<div className="flex items-center justify-between">
|
||||||
|
<Label htmlFor="itemCount">Number of customers</Label>
|
||||||
|
<Select
|
||||||
|
value={String(localSettings.itemCount || 5)}
|
||||||
|
onValueChange={(v) => updateSetting("itemCount", parseInt(v))}
|
||||||
|
>
|
||||||
|
<SelectTrigger className="w-24">
|
||||||
|
<SelectValue />
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
<SelectItem value="3">3</SelectItem>
|
||||||
|
<SelectItem value="5">5</SelectItem>
|
||||||
|
<SelectItem value="10">10</SelectItem>
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
</div>
|
||||||
|
<div className="flex items-center justify-between">
|
||||||
|
<Label htmlFor="showSpent">Show amount spent</Label>
|
||||||
|
<Switch
|
||||||
|
id="showSpent"
|
||||||
|
checked={localSettings.showSpent ?? true}
|
||||||
|
onCheckedChange={(checked) => updateSetting("showSpent", checked)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* Pending Chats Settings */}
|
||||||
|
{widget.id === "pending-chats" && (
|
||||||
|
<div className="space-y-4">
|
||||||
|
<div className="flex items-center justify-between">
|
||||||
|
<Label htmlFor="showPreview">Show message preview</Label>
|
||||||
|
<Switch
|
||||||
|
id="showPreview"
|
||||||
|
checked={localSettings.showPreview ?? true}
|
||||||
|
onCheckedChange={(checked) => updateSetting("showPreview", checked)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* Overview Settings */}
|
||||||
|
{widget.id === "overview" && (
|
||||||
|
<div className="space-y-4">
|
||||||
|
<div className="flex items-center justify-between">
|
||||||
|
<Label htmlFor="showChange">Show percentage change</Label>
|
||||||
|
<Switch
|
||||||
|
id="showChange"
|
||||||
|
checked={localSettings.showChange ?? false}
|
||||||
|
onCheckedChange={(checked) => updateSetting("showChange", checked)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* Quick Actions - no settings */}
|
||||||
|
{widget.id === "quick-actions" && (
|
||||||
|
<p className="text-sm text-muted-foreground text-center py-4">
|
||||||
|
This widget has no customizable settings.
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</ScrollArea>
|
||||||
<div className="space-y-4">
|
|
||||||
{/* Recent Activity Settings */}
|
|
||||||
{widget.id === "recent-activity" && (
|
|
||||||
<div className="space-y-4">
|
|
||||||
<div className="flex items-center justify-between">
|
|
||||||
<Label htmlFor="itemCount">Number of items</Label>
|
|
||||||
<Select
|
|
||||||
value={String(localSettings.itemCount || 10)}
|
|
||||||
onValueChange={(v) => updateSetting("itemCount", parseInt(v))}
|
|
||||||
>
|
|
||||||
<SelectTrigger className="w-24">
|
|
||||||
<SelectValue />
|
|
||||||
</SelectTrigger>
|
|
||||||
<SelectContent>
|
|
||||||
<SelectItem value="5">5</SelectItem>
|
|
||||||
<SelectItem value="10">10</SelectItem>
|
|
||||||
<SelectItem value="15">15</SelectItem>
|
|
||||||
<SelectItem value="20">20</SelectItem>
|
|
||||||
</SelectContent>
|
|
||||||
</Select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{/* Top Products Settings */}
|
|
||||||
{widget.id === "top-products" && (
|
|
||||||
<div className="space-y-4">
|
|
||||||
<div className="flex items-center justify-between">
|
|
||||||
<Label htmlFor="itemCount">Number of products</Label>
|
|
||||||
<Select
|
|
||||||
value={String(localSettings.itemCount || 5)}
|
|
||||||
onValueChange={(v) => updateSetting("itemCount", parseInt(v))}
|
|
||||||
>
|
|
||||||
<SelectTrigger className="w-24">
|
|
||||||
<SelectValue />
|
|
||||||
</SelectTrigger>
|
|
||||||
<SelectContent>
|
|
||||||
<SelectItem value="3">3</SelectItem>
|
|
||||||
<SelectItem value="5">5</SelectItem>
|
|
||||||
<SelectItem value="10">10</SelectItem>
|
|
||||||
</SelectContent>
|
|
||||||
</Select>
|
|
||||||
</div>
|
|
||||||
<div className="flex items-center justify-between">
|
|
||||||
<Label htmlFor="showRevenue">Show revenue</Label>
|
|
||||||
<Switch
|
|
||||||
id="showRevenue"
|
|
||||||
checked={localSettings.showRevenue ?? true}
|
|
||||||
onCheckedChange={(checked) => updateSetting("showRevenue", checked)}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{/* Revenue Chart Settings */}
|
|
||||||
{widget.id === "revenue-chart" && (
|
|
||||||
<div className="space-y-4">
|
|
||||||
<div className="flex items-center justify-between">
|
|
||||||
<Label htmlFor="days">Time period</Label>
|
|
||||||
<Select
|
|
||||||
value={String(localSettings.days || 7)}
|
|
||||||
onValueChange={(v) => updateSetting("days", parseInt(v))}
|
|
||||||
>
|
|
||||||
<SelectTrigger className="w-32">
|
|
||||||
<SelectValue />
|
|
||||||
</SelectTrigger>
|
|
||||||
<SelectContent>
|
|
||||||
<SelectItem value="7">Last 7 days</SelectItem>
|
|
||||||
<SelectItem value="14">Last 14 days</SelectItem>
|
|
||||||
<SelectItem value="30">Last 30 days</SelectItem>
|
|
||||||
</SelectContent>
|
|
||||||
</Select>
|
|
||||||
</div>
|
|
||||||
<div className="flex items-center justify-between">
|
|
||||||
<Label htmlFor="showComparison">Show comparison</Label>
|
|
||||||
<Switch
|
|
||||||
id="showComparison"
|
|
||||||
checked={localSettings.showComparison ?? false}
|
|
||||||
onCheckedChange={(checked) => updateSetting("showComparison", checked)}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{/* Low Stock Settings */}
|
|
||||||
{widget.id === "low-stock" && (
|
|
||||||
<div className="space-y-4">
|
|
||||||
<div className="flex items-center justify-between">
|
|
||||||
<Label htmlFor="threshold">Stock threshold</Label>
|
|
||||||
<Input
|
|
||||||
id="threshold"
|
|
||||||
type="number"
|
|
||||||
className="w-24"
|
|
||||||
value={localSettings.threshold || 5}
|
|
||||||
onChange={(e) => updateSetting("threshold", parseInt(e.target.value) || 5)}
|
|
||||||
min={1}
|
|
||||||
max={100}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="flex items-center justify-between">
|
|
||||||
<Label htmlFor="itemCount">Max items to show</Label>
|
|
||||||
<Select
|
|
||||||
value={String(localSettings.itemCount || 5)}
|
|
||||||
onValueChange={(v) => updateSetting("itemCount", parseInt(v))}
|
|
||||||
>
|
|
||||||
<SelectTrigger className="w-24">
|
|
||||||
<SelectValue />
|
|
||||||
</SelectTrigger>
|
|
||||||
<SelectContent>
|
|
||||||
<SelectItem value="3">3</SelectItem>
|
|
||||||
<SelectItem value="5">5</SelectItem>
|
|
||||||
<SelectItem value="10">10</SelectItem>
|
|
||||||
</SelectContent>
|
|
||||||
</Select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{/* Recent Customers Settings */}
|
|
||||||
{widget.id === "recent-customers" && (
|
|
||||||
<div className="space-y-4">
|
|
||||||
<div className="flex items-center justify-between">
|
|
||||||
<Label htmlFor="itemCount">Number of customers</Label>
|
|
||||||
<Select
|
|
||||||
value={String(localSettings.itemCount || 5)}
|
|
||||||
onValueChange={(v) => updateSetting("itemCount", parseInt(v))}
|
|
||||||
>
|
|
||||||
<SelectTrigger className="w-24">
|
|
||||||
<SelectValue />
|
|
||||||
</SelectTrigger>
|
|
||||||
<SelectContent>
|
|
||||||
<SelectItem value="3">3</SelectItem>
|
|
||||||
<SelectItem value="5">5</SelectItem>
|
|
||||||
<SelectItem value="10">10</SelectItem>
|
|
||||||
</SelectContent>
|
|
||||||
</Select>
|
|
||||||
</div>
|
|
||||||
<div className="flex items-center justify-between">
|
|
||||||
<Label htmlFor="showSpent">Show amount spent</Label>
|
|
||||||
<Switch
|
|
||||||
id="showSpent"
|
|
||||||
checked={localSettings.showSpent ?? true}
|
|
||||||
onCheckedChange={(checked) => updateSetting("showSpent", checked)}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{/* Pending Chats Settings */}
|
|
||||||
{widget.id === "pending-chats" && (
|
|
||||||
<div className="space-y-4">
|
|
||||||
<div className="flex items-center justify-between">
|
|
||||||
<Label htmlFor="showPreview">Show message preview</Label>
|
|
||||||
<Switch
|
|
||||||
id="showPreview"
|
|
||||||
checked={localSettings.showPreview ?? true}
|
|
||||||
onCheckedChange={(checked) => updateSetting("showPreview", checked)}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{/* Overview Settings */}
|
|
||||||
{widget.id === "overview" && (
|
|
||||||
<div className="space-y-4">
|
|
||||||
<div className="flex items-center justify-between">
|
|
||||||
<Label htmlFor="showChange">Show percentage change</Label>
|
|
||||||
<Switch
|
|
||||||
id="showChange"
|
|
||||||
checked={localSettings.showChange ?? false}
|
|
||||||
onCheckedChange={(checked) => updateSetting("showChange", checked)}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{/* Quick Actions - no settings */}
|
|
||||||
{widget.id === "quick-actions" && (
|
|
||||||
<p className="text-sm text-muted-foreground text-center py-4">
|
|
||||||
This widget has no customizable settings.
|
|
||||||
</p>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<DialogFooter>
|
<DialogFooter>
|
||||||
<Button variant="outline" onClick={() => onOpenChange(false)}>
|
<Button variant="outline" onClick={() => onOpenChange(false)}>
|
||||||
|
|||||||
Reference in New Issue
Block a user