localgreenchain/components/mobile/MobileHeader.tsx
Claude c2a1b05677
Implement Agent 10: Mobile Optimization with PWA capabilities
This implements the mobile optimization agent (P3 - Enhancement) with:

PWA Configuration:
- Add next-pwa integration with offline caching strategies
- Create web app manifest for installability
- Add service worker with background sync support
- Create offline fallback page

Mobile Components:
- BottomNav: Touch-friendly bottom navigation bar
- MobileHeader: Responsive header with back navigation
- InstallPrompt: Smart PWA install prompt (iOS & Android)
- SwipeableCard: Gesture-based swipeable cards
- PullToRefresh: Native-like pull to refresh
- QRScanner: Camera-based QR code scanning

Mobile Library:
- camera.ts: Camera access and photo capture utilities
- offline.ts: IndexedDB-based offline storage and sync
- gestures.ts: Touch gesture detection (swipe, pinch, tap)
- pwa.ts: PWA status, install prompts, service worker management

Mobile Pages:
- /m: Mobile dashboard with quick actions and stats
- /m/scan: QR code scanner for plant lookup
- /m/quick-add: Streamlined plant registration form
- /m/profile: User profile with offline status

Dependencies added: next-pwa, idb
2025-11-23 03:56:30 +00:00

101 lines
3.5 KiB
TypeScript

import * as React from 'react';
import Link from 'next/link';
import { useRouter } from 'next/router';
interface MobileHeaderProps {
title?: string;
showBack?: boolean;
rightAction?: React.ReactNode;
}
export function MobileHeader({ title, showBack = false, rightAction }: MobileHeaderProps) {
const router = useRouter();
const handleBack = () => {
if (window.history.length > 1) {
router.back();
} else {
router.push('/m');
}
};
return (
<header className="fixed top-0 left-0 right-0 z-50 bg-white border-b border-gray-200 pt-safe md:hidden">
<div className="flex items-center justify-between h-14 px-4">
{/* Left side */}
<div className="flex items-center w-20">
{showBack ? (
<button
onClick={handleBack}
className="flex items-center justify-center w-10 h-10 -ml-2 rounded-full hover:bg-gray-100 active:bg-gray-200"
aria-label="Go back"
>
<svg
xmlns="http://www.w3.org/2000/svg"
className="h-6 w-6 text-gray-700"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15 19l-7-7 7-7" />
</svg>
</button>
) : (
<Link href="/m">
<a className="flex items-center space-x-2">
<div className="w-8 h-8 bg-green-600 rounded-lg flex items-center justify-center">
<svg
xmlns="http://www.w3.org/2000/svg"
className="h-5 w-5 text-white"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z"
/>
</svg>
</div>
</a>
</Link>
)}
</div>
{/* Center - Title */}
<div className="flex-1 text-center">
<h1 className="text-lg font-semibold text-gray-900 truncate">{title || 'LocalGreenChain'}</h1>
</div>
{/* Right side */}
<div className="flex items-center justify-end w-20">
{rightAction || (
<button
className="flex items-center justify-center w-10 h-10 -mr-2 rounded-full hover:bg-gray-100 active:bg-gray-200"
aria-label="Notifications"
>
<svg
xmlns="http://www.w3.org/2000/svg"
className="h-6 w-6 text-gray-700"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M15 17h5l-1.405-1.405A2.032 2.032 0 0118 14.158V11a6.002 6.002 0 00-4-5.659V5a2 2 0 10-4 0v.341C7.67 6.165 6 8.388 6 11v3.159c0 .538-.214 1.055-.595 1.436L4 17h5m6 0v1a3 3 0 11-6 0v-1m6 0H9"
/>
</svg>
</button>
)}
</div>
</div>
</header>
);
}
export default MobileHeader;