feat: enhance responsive design and layout consistency across various components, including dashboard, statistics, and rules pages
This commit is contained in:
@@ -35,6 +35,7 @@ import { Calendar as CalendarComponent } from "@/components/ui/calendar";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { format } from "date-fns";
|
||||
import { fr } from "date-fns/locale";
|
||||
import { useIsMobile } from "@/hooks/use-mobile";
|
||||
import type { Account, Category } from "@/lib/types";
|
||||
|
||||
type Period = "1month" | "3months" | "6months" | "12months" | "custom" | "all";
|
||||
@@ -601,15 +602,15 @@ export default function StatisticsPage() {
|
||||
description="Analysez vos dépenses et revenus"
|
||||
/>
|
||||
|
||||
<Card className="mb-6">
|
||||
<CardContent className="pt-4">
|
||||
<div className="flex flex-wrap gap-4">
|
||||
<Card className="mb-4 md:mb-6">
|
||||
<CardContent className="pt-3 md:pt-4">
|
||||
<div className="flex flex-wrap gap-2 md:gap-4">
|
||||
<AccountFilterCombobox
|
||||
accounts={data.accounts}
|
||||
folders={data.folders}
|
||||
value={selectedAccounts}
|
||||
onChange={setSelectedAccounts}
|
||||
className="w-[280px]"
|
||||
className="w-full md:w-[280px]"
|
||||
filteredTransactions={transactionsForAccountFilter}
|
||||
/>
|
||||
|
||||
@@ -617,7 +618,7 @@ export default function StatisticsPage() {
|
||||
categories={data.categories}
|
||||
value={selectedCategories}
|
||||
onChange={setSelectedCategories}
|
||||
className="w-[220px]"
|
||||
className="w-full md:w-[220px]"
|
||||
filteredTransactions={transactionsForCategoryFilter}
|
||||
/>
|
||||
|
||||
@@ -632,7 +633,7 @@ export default function StatisticsPage() {
|
||||
}
|
||||
}}
|
||||
>
|
||||
<SelectTrigger className="w-[150px]">
|
||||
<SelectTrigger className="w-full md:w-[150px]">
|
||||
<SelectValue placeholder="Période" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
@@ -648,7 +649,7 @@ export default function StatisticsPage() {
|
||||
{period === "custom" && (
|
||||
<Popover open={isCustomDatePickerOpen} onOpenChange={setIsCustomDatePickerOpen}>
|
||||
<PopoverTrigger asChild>
|
||||
<Button variant="outline" className="w-[280px] justify-start text-left font-normal">
|
||||
<Button variant="outline" className="w-full md:w-[280px] justify-start text-left font-normal">
|
||||
<Calendar className="mr-2 h-4 w-4" />
|
||||
{customStartDate && customEndDate ? (
|
||||
<>
|
||||
@@ -727,7 +728,7 @@ export default function StatisticsPage() {
|
||||
)}
|
||||
|
||||
{internalTransferCategory && (
|
||||
<div className="flex items-center gap-2 px-3 py-2 border border-border rounded-md bg-[var(--card)]">
|
||||
<div className="flex items-center gap-2 px-2 md:px-3 py-1.5 md:py-2 border border-border rounded-md bg-[var(--card)]">
|
||||
<Checkbox
|
||||
id="exclude-internal-transfers"
|
||||
checked={excludeInternalTransfers}
|
||||
@@ -735,7 +736,7 @@ export default function StatisticsPage() {
|
||||
/>
|
||||
<label
|
||||
htmlFor="exclude-internal-transfers"
|
||||
className="text-sm font-medium cursor-pointer select-none"
|
||||
className="text-xs md:text-sm font-medium cursor-pointer select-none"
|
||||
>
|
||||
Exclure Virement interne
|
||||
</label>
|
||||
@@ -771,15 +772,15 @@ export default function StatisticsPage() {
|
||||
</Card>
|
||||
|
||||
{/* Vue d'ensemble */}
|
||||
<section className="mb-8">
|
||||
<h2 className="text-2xl font-semibold mb-4">Vue d'ensemble</h2>
|
||||
<section className="mb-4 md:mb-8">
|
||||
<h2 className="text-lg md:text-2xl font-semibold mb-3 md:mb-4">Vue d'ensemble</h2>
|
||||
<StatsSummaryCards
|
||||
totalIncome={stats.totalIncome}
|
||||
totalExpenses={stats.totalExpenses}
|
||||
avgMonthlyExpenses={stats.avgMonthlyExpenses}
|
||||
formatCurrency={formatCurrency}
|
||||
/>
|
||||
<div className="mt-6">
|
||||
<div className="mt-4 md:mt-6">
|
||||
<BalanceLineChart
|
||||
aggregatedData={stats.aggregatedBalanceData}
|
||||
perAccountData={stats.perAccountBalanceData}
|
||||
@@ -787,7 +788,7 @@ export default function StatisticsPage() {
|
||||
formatCurrency={formatCurrency}
|
||||
/>
|
||||
</div>
|
||||
<div className="mt-6">
|
||||
<div className="mt-4 md:mt-6">
|
||||
<SavingsTrendChart
|
||||
data={stats.savingsTrendData}
|
||||
formatCurrency={formatCurrency}
|
||||
@@ -796,9 +797,9 @@ export default function StatisticsPage() {
|
||||
</section>
|
||||
|
||||
{/* Revenus et Dépenses */}
|
||||
<section className="mb-8">
|
||||
<h2 className="text-2xl font-semibold mb-4">Revenus et Dépenses</h2>
|
||||
<div className="grid gap-6 lg:grid-cols-2">
|
||||
<section className="mb-4 md:mb-8">
|
||||
<h2 className="text-lg md:text-2xl font-semibold mb-3 md:mb-4">Revenus et Dépenses</h2>
|
||||
<div className="grid gap-4 md:gap-6 lg:grid-cols-2">
|
||||
<MonthlyChart
|
||||
data={stats.monthlyChartData}
|
||||
formatCurrency={formatCurrency}
|
||||
@@ -813,7 +814,7 @@ export default function StatisticsPage() {
|
||||
/>
|
||||
</div>
|
||||
{stats.yearOverYearData.length > 0 && (
|
||||
<div className="mt-6">
|
||||
<div className="mt-4 md:mt-6">
|
||||
<YearOverYearChart
|
||||
data={stats.yearOverYearData}
|
||||
formatCurrency={formatCurrency}
|
||||
@@ -823,9 +824,9 @@ export default function StatisticsPage() {
|
||||
</section>
|
||||
|
||||
{/* Analyse par Catégorie */}
|
||||
<section className="mb-8">
|
||||
<h2 className="text-2xl font-semibold mb-4">Analyse par Catégorie</h2>
|
||||
<div className="grid gap-6">
|
||||
<section className="mb-4 md:mb-8">
|
||||
<h2 className="text-lg md:text-2xl font-semibold mb-3 md:mb-4">Analyse par Catégorie</h2>
|
||||
<div className="grid gap-4 md:gap-6">
|
||||
<CategoryPieChart
|
||||
data={stats.categoryChartData}
|
||||
dataByParent={stats.categoryChartDataByParent}
|
||||
@@ -837,7 +838,7 @@ export default function StatisticsPage() {
|
||||
formatCurrency={formatCurrency}
|
||||
/>
|
||||
</div>
|
||||
<div className="mt-6">
|
||||
<div className="hidden md:block mt-4 md:mt-6">
|
||||
<CategoryTrendChart
|
||||
data={stats.categoryTrendData}
|
||||
dataByParent={stats.categoryTrendDataByParent}
|
||||
@@ -845,7 +846,7 @@ export default function StatisticsPage() {
|
||||
formatCurrency={formatCurrency}
|
||||
/>
|
||||
</div>
|
||||
<div className="mt-6">
|
||||
<div className="mt-4 md:mt-6">
|
||||
<TopExpensesList
|
||||
expenses={stats.topExpenses}
|
||||
categories={data.categories}
|
||||
@@ -885,6 +886,7 @@ function ActiveFilters({
|
||||
customStartDate?: Date;
|
||||
customEndDate?: Date;
|
||||
}) {
|
||||
const isMobile = useIsMobile();
|
||||
const hasAccounts = !selectedAccounts.includes("all");
|
||||
const hasCategories = !selectedCategories.includes("all");
|
||||
const hasPeriod = period !== "all";
|
||||
@@ -924,28 +926,28 @@ function ActiveFilters({
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="flex items-center gap-2 mt-3 pt-3 border-t border-border flex-wrap">
|
||||
<Filter className="h-3.5 w-3.5 text-muted-foreground" />
|
||||
<div className="flex items-center gap-1.5 md:gap-2 mt-2 md:mt-3 pt-2 md:pt-3 border-t border-border flex-wrap">
|
||||
<Filter className="h-3 w-3 md:h-3.5 md:w-3.5 text-muted-foreground" />
|
||||
|
||||
{selectedAccs.map((acc) => (
|
||||
<Badge key={acc.id} variant="secondary" className="gap-1 text-xs font-normal">
|
||||
<Wallet className="h-3 w-3" />
|
||||
<Badge key={acc.id} variant="secondary" className="gap-0.5 md:gap-1 text-[10px] md:text-xs font-normal">
|
||||
<Wallet className="h-2.5 w-2.5 md:h-3 md:w-3" />
|
||||
{acc.name}
|
||||
<button
|
||||
onClick={() => onRemoveAccount(acc.id)}
|
||||
className="ml-1 hover:text-foreground"
|
||||
className="ml-0.5 md:ml-1 hover:text-foreground"
|
||||
>
|
||||
<X className="h-3 w-3" />
|
||||
<X className="h-2.5 w-2.5 md:h-3 md:w-3" />
|
||||
</button>
|
||||
</Badge>
|
||||
))}
|
||||
|
||||
{isUncategorized && (
|
||||
<Badge variant="secondary" className="gap-1 text-xs font-normal">
|
||||
<CircleSlash className="h-3 w-3" />
|
||||
<Badge variant="secondary" className="gap-0.5 md:gap-1 text-[10px] md:text-xs font-normal">
|
||||
<CircleSlash className="h-2.5 w-2.5 md:h-3 md:w-3" />
|
||||
Non catégorisé
|
||||
<button onClick={onClearCategories} className="ml-1 hover:text-foreground">
|
||||
<X className="h-3 w-3" />
|
||||
<button onClick={onClearCategories} className="ml-0.5 md:ml-1 hover:text-foreground">
|
||||
<X className="h-2.5 w-2.5 md:h-3 md:w-3" />
|
||||
</button>
|
||||
</Badge>
|
||||
)}
|
||||
@@ -954,36 +956,36 @@ function ActiveFilters({
|
||||
<Badge
|
||||
key={cat.id}
|
||||
variant="secondary"
|
||||
className="gap-1 text-xs font-normal"
|
||||
className="gap-0.5 md:gap-1 text-[10px] md:text-xs font-normal"
|
||||
style={{
|
||||
backgroundColor: `${cat.color}15`,
|
||||
borderColor: `${cat.color}30`,
|
||||
}}
|
||||
>
|
||||
<CategoryIcon icon={cat.icon} color={cat.color} size={12} />
|
||||
<CategoryIcon icon={cat.icon} color={cat.color} size={isMobile ? 10 : 12} />
|
||||
{cat.name}
|
||||
<button
|
||||
onClick={() => onRemoveCategory(cat.id)}
|
||||
className="ml-1 hover:text-foreground"
|
||||
className="ml-0.5 md:ml-1 hover:text-foreground"
|
||||
>
|
||||
<X className="h-3 w-3" />
|
||||
<X className="h-2.5 w-2.5 md:h-3 md:w-3" />
|
||||
</button>
|
||||
</Badge>
|
||||
))}
|
||||
|
||||
{hasPeriod && (
|
||||
<Badge variant="secondary" className="gap-1 text-xs font-normal">
|
||||
<Calendar className="h-3 w-3" />
|
||||
<Badge variant="secondary" className="gap-0.5 md:gap-1 text-[10px] md:text-xs font-normal">
|
||||
<Calendar className="h-2.5 w-2.5 md:h-3 md:w-3" />
|
||||
{getPeriodLabel(period)}
|
||||
<button onClick={onClearPeriod} className="ml-1 hover:text-foreground">
|
||||
<X className="h-3 w-3" />
|
||||
<button onClick={onClearPeriod} className="ml-0.5 md:ml-1 hover:text-foreground">
|
||||
<X className="h-2.5 w-2.5 md:h-3 md:w-3" />
|
||||
</button>
|
||||
</Badge>
|
||||
)}
|
||||
|
||||
<button
|
||||
onClick={clearAll}
|
||||
className="text-xs text-muted-foreground hover:text-foreground ml-auto"
|
||||
className="text-[10px] md:text-xs text-muted-foreground hover:text-foreground ml-auto"
|
||||
>
|
||||
Effacer tout
|
||||
</button>
|
||||
|
||||
Reference in New Issue
Block a user