| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125 |
- import React, { useState } from 'react';
- import { RefreshCw, User, LogOut, CheckCircle2 } from 'lucide-react';
- import { useAuth } from '../context/AuthContext';
- import { syncAPI } from '../api';
- export const Navbar = ({ activeTab, setActiveTab, onOpenAuthModal }) => {
- const { user, logout } = useAuth();
- const [syncing, setSyncing] = useState(false);
- const [syncToast, setSyncToast] = useState(false);
- // Format current date matching iOS app format
- const currentDateFormatted = (() => {
- const d = new Date();
- const year = d.getFullYear();
- const month = d.getMonth() + 1;
- const date = d.getDate();
- const weekDays = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'];
- const weekDay = weekDays[d.getDay()];
- return `${year}年${month}月${date}日 ${weekDay}`;
- })();
- const handleSyncNow = async () => {
- if (!user) {
- if (onOpenAuthModal) onOpenAuthModal();
- return;
- }
- setSyncing(true);
- try {
- await syncAPI.triggerManualSync();
- setSyncToast(true);
- setTimeout(() => setSyncToast(false), 3000);
- } catch (e) {
- console.warn("Manual sync failed:", e);
- } finally {
- setSyncing(false);
- }
- };
- return (
- <header className="sticky top-0 z-40 w-full bg-[#F8F9FA]/90 backdrop-blur-md border-b border-black/5 px-4 sm:px-8 py-3.5 flex items-center justify-between">
- {/* Left Title Section matching iOS TopBar screenshot */}
- <div
- className="flex items-center space-x-3.5 cursor-pointer select-none"
- onClick={() => setActiveTab('dashboard')}
- >
- <div>
- <div className="flex items-center space-x-2">
- <h1 className="text-xs font-bold font-mono tracking-widest-tech uppercase text-[#1D1D1F] leading-tight">
- 星痕 现场 记录
- </h1>
- </div>
- <p className="text-[13px] text-[#8E8E93] font-sans leading-tight mt-0.5">
- {currentDateFormatted}
- </p>
- </div>
- </div>
- {/* Center Status Indicator & Sync Actions */}
- <div className="flex items-center space-x-3">
- {/* iOS Ready Status Badge matching screenshot */}
- <div className="flex items-center space-x-1.5 px-2.5 py-1 rounded-md bg-white border border-black/15 text-[10px] font-mono font-semibold text-[#8E8E93] shadow-2xs">
- <span className="w-1.5 h-1.5 rounded-full bg-[#34C759]"></span>
- <span>就绪</span>
- </div>
- {syncToast && (
- <div className="hidden sm:flex items-center space-x-1.5 px-3 py-1 rounded-md bg-emerald-50 border border-emerald-200 text-emerald-700 text-xs animate-fade-in">
- <CheckCircle2 className="w-3.5 h-3.5" />
- <span>已同步至云端</span>
- </div>
- )}
- <button
- onClick={handleSyncNow}
- disabled={syncing}
- className="flex items-center space-x-2 px-3 py-1.5 text-xs font-medium text-slate-700 bg-white hover:bg-slate-50 border border-black/10 rounded-lg shadow-2xs transition-all"
- >
- <RefreshCw className={`w-3.5 h-3.5 text-slate-600 ${syncing ? 'animate-spin' : ''}`} />
- <span className="hidden sm:inline">{syncing ? '同步中...' : '手动同步'}</span>
- </button>
- </div>
- {/* Right Controls: User Card / Auth button */}
- <div className="flex items-center space-x-2">
- {user ? (
- <div className="flex items-center space-x-2 bg-white px-2.5 py-1.5 rounded-xl border border-black/10 shadow-2xs">
- <img
- src={user?.avatarURL || "/spark-logo.svg"}
- alt="Avatar"
- className="w-7 h-7 rounded-lg object-cover ring-1 ring-black/10"
- />
- <div className="hidden sm:block text-left">
- <div className="text-xs font-semibold text-[#1D1D1F] leading-tight">{user.username}</div>
- <div className="text-[10px] text-[#8E8E93] leading-tight font-mono">{user.phoneNumber || user.email || `ID: ${String(user.id || '').substring(0, 6)}`}</div>
- </div>
- <button
- onClick={() => setActiveTab('profile')}
- className="p-1 text-slate-500 hover:text-slate-900 transition-colors"
- title="个人主页"
- >
- <User className="w-4 h-4" />
- </button>
-
- <button
- onClick={() => logout()}
- className="p-1 text-slate-500 hover:text-rose-600 transition-colors"
- title="退出登录"
- >
- <LogOut className="w-4 h-4" />
- </button>
- </div>
- ) : (
- <button
- onClick={onOpenAuthModal}
- className="flex items-center space-x-2 bg-slate-900 text-white dark:bg-white dark:text-slate-950 px-3.5 py-1.5 rounded-xl text-xs font-semibold shadow-2xs hover:opacity-90 transition-all"
- >
- <User className="w-3.5 h-3.5" />
- <span>登录 / 注册</span>
- </button>
- )}
- </div>
- </header>
- );
- };
|