S SmartDocs
系列: Golden-Hour-backend-layer-2 typescript 203 行 · 更新於 2026-02-22

StaffManagement.tsx

Golden-Hour-backend-layer-2/pages/StaffManagement.tsx


import React, { useState } from 'react';

interface StaffMember {
  name: string;
  role: string;
  dept: string;
  status: 'On Duty' | 'On Leave' | 'Remote';
  shift: string;
}

interface ToDoItem {
  id: string;
  task: string;
  completed: boolean;
}

const ProtocolBar: React.FC = () => (
  <div className="fixed bottom-12 left-1/2 -translate-x-1/2 bg-white/90 backdrop-blur-md border border-[#c5a059]/20 px-10 py-5 rounded-full gallery-shadow flex items-center space-x-12 z-50 transition-all hover:border-[#c5a059]/40 group">
    <button className="flex items-center space-x-3 text-slate-400 hover:text-slate-900 transition-all">
      <i className="fa-solid fa-magnifying-glass text-[9px] text-[#c5a059]"></i>
      <span className="text-[8px] font-bold uppercase tracking-[0.3em]">Search</span>
    </button>
    <div className="w-[0.5px] h-4 bg-[#c5a059]/20"></div>
    <button className="flex items-center space-x-3 text-slate-400 hover:text-slate-900 transition-all">
      <i className="fa-solid fa-plus text-[9px] text-[#c5a059]"></i>
      <span className="text-[8px] font-bold uppercase tracking-[0.3em]">Create</span>
    </button>
  </div>
);

const StaffManagement: React.FC = () => {
  const [activeTab, setActiveTab] = useState<'Workspace' | 'Directory'>('Workspace');
  const [isOnDuty, setIsOnDuty] = useState(false);
  const [todos, setTodos] = useState<ToDoItem[]>([
    { id: '1', task: 'Review Villa 04 maintenance report', completed: false },
    { id: '2', task: 'Coordinate with Chef for tonight\'s VIP dinner', completed: true },
    { id: '3', task: 'Verify arrival details for the Miller party', completed: false },
    { id: '4', task: 'Update inventory for cleaning supplies', completed: false },
  ]);

  const staff: StaffMember[] = [
    { name: 'Admin One', role: 'IT Manager', dept: 'IT', status: 'On Duty', shift: 'Morning' },
    { name: 'Maria Garcia', role: 'Housekeeping Supervisor', dept: 'Operations', status: 'On Leave', shift: 'N/A' },
    { name: 'James Wilson', role: 'Front Desk Lead', dept: 'Guest Services', status: 'On Duty', shift: 'Evening' },
    { name: 'Linda Zhang', role: 'Chief Accountant', dept: 'Finance', status: 'Remote', shift: 'Morning' },
  ];

  const toggleTodo = (id: string) => {
    setTodos(todos.map(t => t.id === id ? { ...t, completed: !t.completed } : t));
  };

  return (
    <div className="relative pb-32">
      <div className="fade-in-section space-y-16">
        {/* Editorial Header */}
        <div className="flex flex-col md:flex-row md:items-end justify-between gap-10 border-b border-[#c5a059]/10 pb-12 px-2">
          <div className="flex items-baseline space-x-6">
            <span className="font-serif italic text-6xl text-slate-200">Staff</span>
            <div>
              <h2 className="font-serif italic text-6xl text-slate-900 tracking-tight">Atelier</h2>
              <p className="text-[10px] font-black uppercase tracking-[0.6em] text-[#c5a059] mt-2">Operations & Personnel Hub</p>
            </div>
          </div>
          
          <div className="flex bg-[#fdfcf9] p-1 border border-[#c5a059]/10 rounded-full">
            <button 
              onClick={() => setActiveTab('Workspace')}
              className={`px-10 py-3 rounded-full text-[9px] font-black uppercase tracking-[0.4em] transition-all ${activeTab === 'Workspace' ? 'bg-black text-white shadow-xl' : 'text-slate-300 hover:text-slate-600'}`}
            >
              Workspace
            </button>
            <button 
              onClick={() => setActiveTab('Directory')}
              className={`px-10 py-3 rounded-full text-[9px] font-black uppercase tracking-[0.4em] transition-all ${activeTab === 'Directory' ? 'bg-black text-white shadow-xl' : 'text-slate-300 hover:text-slate-600'}`}
            >
              Directory
            </button>
          </div>
        </div>

        {activeTab === 'Workspace' ? (
          <div className="grid grid-cols-1 lg:grid-cols-3 gap-12">
            <div className="lg:col-span-2 space-y-12">
              <div className="bg-[#1a1a1a] rounded-[3rem] p-12 gallery-shadow relative overflow-hidden group">
                <div className="absolute top-0 right-0 w-32 h-32 bg-[#c5a059]/10 rounded-full blur-3xl -mr-16 -mt-16 group-hover:bg-[#c5a059]/20 transition-all duration-1000"></div>
                <div className="relative z-10">
                  <div className="flex items-center justify-between mb-8">
                    <span className="text-[10px] font-black uppercase tracking-[0.6em] text-[#c5a059]">Golden Hour Bulletins</span>
                    <span className="text-[9px] font-serif italic text-slate-500">Edition: {new Date().toLocaleDateString()}</span>
                  </div>
                  <div className="space-y-6">
                    <div className="border-l-2 border-[#c5a059]/30 pl-8 py-2">
                      <h3 className="font-serif italic text-3xl text-white mb-2">Quarterly Gala Scheduled</h3>
                      <p className="text-slate-400 text-sm leading-relaxed">All staff are required for the orientation on the 15th. Please ensure shift swaps are finalized by Friday.</p>
                    </div>
                    <div className="border-l-2 border-[#c5a059]/30 pl-8 py-2">
                      <h3 className="font-serif italic text-3xl text-white mb-2">New Security Protocol</h3>
                      <p className="text-slate-400 text-sm leading-relaxed">Biometric updates for the main vault will take place starting 09:00 tomorrow.</p>
                    </div>
                  </div>
                </div>
              </div>

              <div className="bg-white rounded-[3rem] p-12 border border-[#c5a059]/10 gallery-shadow">
                 <div className="flex items-center justify-between mb-10 border-b border-[#c5a059]/5 pb-8">
                    <div>
                      <h3 className="font-serif italic text-4xl text-slate-900">Daily Protocol</h3>
                      <p className="text-[9px] font-black uppercase tracking-[0.4em] text-slate-300 mt-2">Personal Tasks & Assignments</p>
                    </div>
                 </div>
                 <div className="space-y-1">
                   {todos.map(todo => (
                     <div 
                      key={todo.id} 
                      onClick={() => toggleTodo(todo.id)}
                      className="flex items-center py-5 px-4 group cursor-pointer hover:bg-[#fdfcf9] transition-all rounded-2xl"
                     >
                       <div className={`w-6 h-6 rounded-full border flex items-center justify-center transition-all mr-6 ${
                         todo.completed ? 'bg-black border-black' : 'bg-transparent border-[#c5a059]/20 group-hover:border-[#c5a059]'
                       }`}>
                         {todo.completed && <i className="fa-solid fa-check text-[10px] text-[#c5a059]"></i>}
                       </div>
                       <span className={`text-lg font-serif italic transition-all ${
                         todo.completed ? 'text-slate-300 line-through' : 'text-slate-700'
                       }`}>
                         {todo.task}
                       </span>
                     </div>
                   ))}
                 </div>
              </div>
            </div>

            <div className="space-y-12">
              <div className="bg-white rounded-[3rem] p-12 border border-[#c5a059]/10 gallery-shadow text-center">
                 <span className="text-[10px] font-black uppercase tracking-[0.6em] text-slate-300 block mb-10">Attendance Console</span>
                 <div className="mb-12">
                   <p className="font-serif italic text-6xl text-slate-900 tabular-nums">{new Date().toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })}</p>
                   <p className="text-[10px] font-black uppercase tracking-[0.3em] text-[#c5a059] mt-4">{new Date().toLocaleDateString('en-US', { weekday: 'long' })}</p>
                 </div>
                 
                 <div className="grid grid-cols-1 gap-4">
                   <button 
                    onClick={() => setIsOnDuty(true)}
                    className={`py-8 rounded-[2rem] text-[10px] font-black uppercase tracking-[0.5em] transition-all duration-700 ${
                      isOnDuty 
                      ? 'bg-[#c5a059]/10 text-[#c5a059] border border-[#c5a059]/20' 
                      : 'bg-white border border-slate-100 text-slate-300 hover:border-[#c5a059] hover:text-black'
                    }`}
                   >
                     {isOnDuty ? <i className="fa-solid fa-circle-dot mr-3 animate-pulse"></i> : <i className="fa-solid fa-power-off mr-3"></i>}
                     Clock In
                   </button>
                   <button 
                    onClick={() => setIsOnDuty(false)}
                    className="py-8 rounded-[2rem] bg-white border border-slate-100 text-slate-300 hover:text-rose-600 hover:border-rose-100 transition-all text-[10px] font-black uppercase tracking-[0.5em]"
                   >
                     Clock Out
                   </button>
                 </div>
              </div>
            </div>
          </div>
        ) : (
          <div className="bg-white rounded-[4rem] border border-[#c5a059]/5 overflow-hidden gallery-shadow">
            <div className="p-12 border-b border-[#c5a059]/5 flex flex-col md:flex-row md:items-center justify-between gap-8">
              <h3 className="font-serif italic text-4xl text-slate-900">Personnel Archive</h3>
            </div>
            <div className="p-12 grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8">
              {staff.map((person, idx) => (
                <div key={idx} className="bg-[#fdfcf9] rounded-[2.5rem] p-10 border border-[#c5a059]/5 hover:border-[#c5a059]/20 transition-all duration-700 group relative">
                  <div className="absolute top-8 right-8 flex space-x-2 opacity-0 group-hover:opacity-100 transition-all">
                    <button className="text-slate-300 hover:text-[#c5a059]"><i className="fa-solid fa-pen-nib text-xs"></i></button>
                    <button className="text-slate-300 hover:text-rose-600"><i className="fa-solid fa-trash-can text-xs"></i></button>
                  </div>
                  <img src={`https://picsum.photos/seed/${person.name}/100/100`} className="w-20 h-20 rounded-2xl grayscale group-hover:grayscale-0 transition-all duration-1000 mb-8" />
                  <h4 className="font-serif italic text-2xl text-slate-900">{person.name}</h4>
                  <p className="text-[10px] font-black uppercase tracking-[0.4em] text-[#c5a059] mt-2 mb-8">{person.role}</p>
                  <div className="space-y-4 pt-8 border-t border-[#c5a059]/5">
                     <div className="flex justify-between items-center">
                        <span className="text-[8px] font-black uppercase tracking-widest text-slate-300">Section</span>
                        <span className="text-[9px] font-bold uppercase tracking-widest text-slate-600">{person.dept}</span>
                     </div>
                     <div className="flex justify-between items-center">
                        <span className="text-[8px] font-black uppercase tracking-widest text-slate-300">Protocol</span>
                        <span className={`text-[9px] font-black uppercase tracking-widest ${
                          person.status === 'On Duty' ? 'text-emerald-500' : 'text-slate-300'
                        }`}>{person.status}</span>
                     </div>
                  </div>
                </div>
              ))}
            </div>
          </div>
        )}
      </div>
      <ProtocolBar />
    </div>
  );
};

export default StaffManagement;

相關文章