'use client' import { useState, useEffect } from 'react' import apiClient from '@/lib/api-client' import AlertDialog from '@/components/ui/AlertDialog' interface CompanyData { id: number code: string name: string name_eng: string | null tax_id: string | null prefix: string tel: string | null add: string | null url: string | null keycloak_realm: string | null is_sysmana: boolean plan_id: string max_users: number storage_quota_gb: number status: string is_active: boolean edit_by: string | null created_at: string | null updated_at: string | null } export default function CompanyInfoPage() { const [companyData, setCompanyData] = useState(null) const [loading, setLoading] = useState(true) const [saving, setSaving] = useState(false) const [isEditing, setIsEditing] = useState(false) // 表單資料 const [formData, setFormData] = useState({ name: '', name_eng: '', tax_id: '', tel: '', add: '', url: '', }) // 對話框狀態 const [alertDialog, setAlertDialog] = useState<{ isOpen: boolean title: string message: string type: 'info' | 'warning' | 'error' | 'success' }>({ isOpen: false, title: '', message: '', type: 'info', }) // 載入公司資料 useEffect(() => { loadCompanyData() }, []) const loadCompanyData = async () => { try { setLoading(true) const response: any = await apiClient.get('/tenants/current') setCompanyData(response) setFormData({ name: response.name || '', name_eng: response.name_eng || '', tax_id: response.tax_id || '', tel: response.tel || '', add: response.add || '', url: response.url || '', }) } catch (error: any) { console.error('Failed to load company data:', error) setAlertDialog({ isOpen: true, title: '載入失敗', message: error.response?.data?.detail || '無法載入公司資料', type: 'error', }) } finally { setLoading(false) } } const handleChange = (field: string, value: string) => { setFormData(prev => ({ ...prev, [field]: value })) } const handleEdit = () => { setIsEditing(true) } const handleCancel = () => { if (companyData) { setFormData({ name: companyData.name || '', name_eng: companyData.name_eng || '', tax_id: companyData.tax_id || '', tel: companyData.tel || '', add: companyData.add || '', url: companyData.url || '', }) } setIsEditing(false) } const handleSubmit = async (e: React.FormEvent) => { e.preventDefault() setSaving(true) try { // 驗證 if (!formData.name) { setAlertDialog({ isOpen: true, title: '欄位驗證', message: '公司名稱為必填欄位', type: 'warning', }) setSaving(false) return } // 驗證統一編號格式 (8位數字) if (formData.tax_id && (!/^\d{8}$/.test(formData.tax_id))) { setAlertDialog({ isOpen: true, title: '欄位驗證', message: '統一編號必須為8位數字', type: 'warning', }) setSaving(false) return } // 送出更新 await apiClient.patch('/tenants/current', formData) // 重新載入資料 await loadCompanyData() setIsEditing(false) setAlertDialog({ isOpen: true, title: '儲存成功', message: '公司資料已成功更新', type: 'success', }) } catch (error: any) { console.error('Failed to update company data:', error) setAlertDialog({ isOpen: true, title: '儲存失敗', message: error.response?.data?.detail || '更新失敗,請稍後再試', type: 'error', }) } finally { setSaving(false) } } if (loading) { return (
載入中...
) } if (!companyData) { return (
無法載入公司資料
) } return (
{/* Header */}

公司資料維護

管理您的公司基本資料

{!isEditing && ( )}
{/* Card */}
{/* Card Header */}

{companyData.name} - 基本資料

{/* Card Body */}
{/* Row 1: 租戶代碼 + 員工編號前綴 (唯讀) */}
{/* Row 2: 公司名稱 + 公司英文名稱 */}
handleChange('name', e.target.value)} disabled={!isEditing} className={`w-full px-3 py-2 border border-gray-300 rounded-lg text-sm ${ isEditing ? 'text-gray-900 placeholder:text-gray-500 focus:outline-none focus:ring-2 focus:ring-blue-500' : 'bg-gray-50 text-gray-700 cursor-not-allowed' }`} placeholder="例如: 匠耘營運有限公司" required />
handleChange('name_eng', e.target.value)} disabled={!isEditing} className={`w-full px-3 py-2 border border-gray-300 rounded-lg text-sm ${ isEditing ? 'text-gray-900 placeholder:text-gray-500 focus:outline-none focus:ring-2 focus:ring-blue-500' : 'bg-gray-50 text-gray-700 cursor-not-allowed' }`} placeholder="例如: Porsche World Co., Ltd." />
{/* Row 3: 統一編號 + 公司電話 */}
handleChange('tax_id', e.target.value)} disabled={!isEditing} className={`w-full px-3 py-2 border border-gray-300 rounded-lg text-sm ${ isEditing ? 'text-gray-900 placeholder:text-gray-500 focus:outline-none focus:ring-2 focus:ring-blue-500' : 'bg-gray-50 text-gray-700 cursor-not-allowed' }`} placeholder="例如: 12345678" maxLength={8} />
handleChange('tel', e.target.value)} disabled={!isEditing} className={`w-full px-3 py-2 border border-gray-300 rounded-lg text-sm ${ isEditing ? 'text-gray-900 placeholder:text-gray-500 focus:outline-none focus:ring-2 focus:ring-blue-500' : 'bg-gray-50 text-gray-700 cursor-not-allowed' }`} placeholder="例如: 02-12345678" />
{/* Row 4: 公司地址 */}
handleChange('add', e.target.value)} disabled={!isEditing} className={`w-full px-3 py-2 border border-gray-300 rounded-lg text-sm ${ isEditing ? 'text-gray-900 placeholder:text-gray-500 focus:outline-none focus:ring-2 focus:ring-blue-500' : 'bg-gray-50 text-gray-700 cursor-not-allowed' }`} placeholder="例如: 台北市信義區信義路五段7號" />
{/* Row 5: 公司網站 */}
handleChange('url', e.target.value)} disabled={!isEditing} className={`w-full px-3 py-2 border border-gray-300 rounded-lg text-sm ${ isEditing ? 'text-gray-900 placeholder:text-gray-500 focus:outline-none focus:ring-2 focus:ring-blue-500' : 'bg-gray-50 text-gray-700 cursor-not-allowed' }`} placeholder="例如: https://www.porscheworld.tw" />
{/* 系統資訊 (唯讀) */}

系統資訊

{companyData.plan_id}
{companyData.max_users}
{companyData.storage_quota_gb}
{companyData.status}
{companyData.edit_by || '-'}
{companyData.updated_at ? new Date(companyData.updated_at).toLocaleString('zh-TW') : '-'}
{/* 操作按鈕 */} {isEditing && (
)}
{/* Alert Dialog */} setAlertDialog({ ...alertDialog, isOpen: false })} />
) }