Add sleek mobile navigation buttons to dashboard with theme support and synced scroll tracking
This commit is contained in:
parent
4f44182b59
commit
35b2ec9e8c
@ -1,6 +1,6 @@
|
||||
'use client';
|
||||
|
||||
import { useState, useEffect, useCallback } from 'react';
|
||||
import { useState, useEffect, useCallback, useRef } from 'react';
|
||||
import { User } from '@/lib/session';
|
||||
import {
|
||||
fetchPreferences,
|
||||
@ -34,7 +34,7 @@ import { HealthTimelineCard } from './HealthTimelineCard';
|
||||
import { SavingsTrackerCard } from './SavingsTrackerCard';
|
||||
import { MoodTracker } from './MoodTracker';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { PlusCircle } from 'lucide-react';
|
||||
import { PlusCircle, ChevronLeft, ChevronRight } from 'lucide-react';
|
||||
import { useTheme } from '@/lib/theme-context';
|
||||
import { getTodayString } from '@/lib/date-utils';
|
||||
|
||||
@ -53,8 +53,29 @@ export function Dashboard({ user }: DashboardProps) {
|
||||
const [newBadge, setNewBadge] = useState<BadgeDefinition | null>(null);
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
const [refreshKey, setRefreshKey] = useState(0);
|
||||
const [currentPage, setCurrentPage] = useState(0);
|
||||
const swipeContainerRef = useRef<HTMLDivElement>(null);
|
||||
const { theme } = useTheme();
|
||||
|
||||
const handleScroll = useCallback(() => {
|
||||
if (!swipeContainerRef.current) return;
|
||||
const scrollLeft = swipeContainerRef.current.scrollLeft;
|
||||
const width = swipeContainerRef.current.offsetWidth;
|
||||
const page = Math.round(scrollLeft / width);
|
||||
if (page !== currentPage) {
|
||||
setCurrentPage(page);
|
||||
}
|
||||
}, [currentPage]);
|
||||
|
||||
const scrollToPage = (pageIndex: number) => {
|
||||
if (!swipeContainerRef.current) return;
|
||||
const width = swipeContainerRef.current.offsetWidth;
|
||||
swipeContainerRef.current.scrollTo({
|
||||
left: pageIndex * width,
|
||||
behavior: 'smooth'
|
||||
});
|
||||
};
|
||||
|
||||
const loadData = useCallback(async () => {
|
||||
const [prefs, usage, achvs, savings] = await Promise.all([
|
||||
fetchPreferences(),
|
||||
@ -235,10 +256,41 @@ export function Dashboard({ user }: DashboardProps) {
|
||||
</div>
|
||||
|
||||
{/* Dashboard Sections */}
|
||||
<div className="space-y-10 sm:space-y-12">
|
||||
<div className="space-y-10 sm:space-y-12 relative">
|
||||
{/* Mobile Navigation Buttons */}
|
||||
<div className="sm:hidden">
|
||||
{currentPage > 0 && (
|
||||
<button
|
||||
onClick={() => scrollToPage(currentPage - 1)}
|
||||
className="fixed left-2 top-1/2 -translate-y-1/2 z-[60] p-3 rounded-full glass border border-white/10 shadow-2xl active:scale-90 transition-all duration-300 group"
|
||||
style={{
|
||||
background: theme === 'light' ? 'rgba(255, 255, 255, 0.7)' : 'rgba(0, 0, 0, 0.4)',
|
||||
backdropFilter: 'blur(12px)'
|
||||
}}
|
||||
>
|
||||
<ChevronLeft className="h-6 w-6 text-primary group-hover:scale-110" />
|
||||
</button>
|
||||
)}
|
||||
{currentPage < 3 && (
|
||||
<button
|
||||
onClick={() => scrollToPage(currentPage + 1)}
|
||||
className="fixed right-2 top-1/2 -translate-y-1/2 z-[60] p-3 rounded-full glass border border-white/10 shadow-2xl active:scale-90 transition-all duration-300 group"
|
||||
style={{
|
||||
background: theme === 'light' ? 'rgba(255, 255, 255, 0.7)' : 'rgba(0, 0, 0, 0.4)',
|
||||
backdropFilter: 'blur(12px)'
|
||||
}}
|
||||
>
|
||||
<ChevronRight className="h-6 w-6 text-primary group-hover:scale-110" />
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* SECTION: Mobile Swipe Ecosystem */}
|
||||
<div className="swipe-container sm:space-y-12 sm:block">
|
||||
<div
|
||||
ref={swipeContainerRef}
|
||||
onScroll={handleScroll}
|
||||
className="swipe-container sm:space-y-12 sm:block"
|
||||
>
|
||||
|
||||
{/* SLIDE 1: Mindset (Mood & Personalized Plan) */}
|
||||
<div className="swipe-item space-y-4">
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user