'use client';
import { useState, useEffect } from 'react';
import { Loader2, AlertCircle, CheckCircle, Info, Pencil } from 'lucide-react';
import { getClubProfile, updateClubProfile } from '@/src/lib/api/courts';
import type { ClubProfile, ClubProfileUpdateRequest} from '@/src/types/courts';
import { COMMON_TIMEZONES, isValidEmail, isValidUrl } from '@/src/types/courts';
/**
* Editable Field Component - Click to edit with pencil icon
*/
interface EditableFieldProps {
fieldName: string;
value: string;
onChange: (value: string) => void;
isEditing: boolean;
onToggleEdit: () => void;
placeholder?: string;
maxLength?: number;
type?: 'text' | 'email' | 'tel' | 'url';
error?: string;
disabled?: boolean;
}
function EditableField({
fieldName,
value,
onChange,
isEditing,
onToggleEdit,
placeholder,
maxLength,
type = 'text',
error,
disabled = false,
}: EditableFieldProps) {
const hasValue = value.trim().length > 0;
if (isEditing || !hasValue) {
return (
onChange(e.target.value)}
onBlur={() => hasValue && onToggleEdit()}
autoFocus
placeholder={placeholder}
maxLength={maxLength}
className={`w-full px-4 py-3 border-2 rounded-lg font-medium transition-colors ${
error
? 'border-red-300 focus:border-red-500'
: 'border-slate-200 focus:border-slate-900'
} focus:outline-none`}
disabled={disabled}
/>
);
}
return (
);
}
interface ClubProfileTabProps {
clubId: number;
onUpdate?: () => void;
}
export default function ClubProfileTab({ clubId, onUpdate }: ClubProfileTabProps) {
const [profile, setProfile] = useState(null);
const [loading, setLoading] = useState(true);
const [saving, setSaving] = useState(false);
const [error, setError] = useState(null);
const [success, setSuccess] = useState(false);
const [errors, setErrors] = useState>({});
// Form state
const [name, setName] = useState('');
const [timezone, setTimezone] = useState('');
const [addressLine1, setAddressLine1] = useState('');
const [addressLine2, setAddressLine2] = useState('');
const [city, setCity] = useState('');
const [postalCode, setPostalCode] = useState('');
const [country, setCountry] = useState('');
const [phone, setPhone] = useState('');
const [email, setEmail] = useState('');
const [website, setWebsite] = useState('');
// Edit mode tracking for each field
const [editingFields, setEditingFields] = useState>(new Set());
useEffect(() => {
loadProfile();
}, [clubId]);
async function loadProfile() {
setLoading(true);
const result = await getClubProfile(clubId);
if (result.success) {
const prof = result.data;
setProfile(prof);
// Populate form - read from settings structure
setName(prof.name);
setTimezone(prof.timezone);
setAddressLine1(prof.settings?.address?.line_1 || '');
setAddressLine2(prof.settings?.address?.line_2 || '');
setCity(prof.settings?.address?.city || '');
setPostalCode(prof.settings?.address?.postal_code || '');
setCountry(prof.settings?.address?.country || '');
setPhone(prof.settings?.contact?.phone || '');
setEmail(prof.settings?.contact?.email || '');
setWebsite(prof.settings?.contact?.website || '');
setError(null);
} else {
setError(result.error.detail);
}
setLoading(false);
}
function validateForm(): boolean {
const newErrors: Record = {};
if (!name || name.trim().length === 0) {
newErrors.name = 'Name is required';
}
if (!timezone) {
newErrors.timezone = 'Timezone is required';
}
if (email && !isValidEmail(email)) {
newErrors.email = 'Invalid email format';
}
if (website && !isValidUrl(website)) {
newErrors.website = 'Invalid URL format (must include http:// or https://)';
}
setErrors(newErrors);
return Object.keys(newErrors).length === 0;
}
async function handleSubmit(e: React.FormEvent) {
e.preventDefault();
if (!validateForm()) {
return;
}
setSaving(true);
setError(null);
setSuccess(false);
// Build settings structure, preserving existing settings
const updatedSettings = {
...profile?.settings,
address: {
...profile?.settings?.address,
line_1: addressLine1.trim() || undefined,
line_2: addressLine2.trim() || undefined,
city: city.trim() || undefined,
postal_code: postalCode.trim() || undefined,
country: country.trim() || undefined,
},
contact: {
...profile?.settings?.contact,
phone: phone.trim() || undefined,
email: email.trim() || undefined,
website: website.trim() || undefined,
},
};
const request: ClubProfileUpdateRequest = {
name: name.trim(),
timezone,
settings: updatedSettings,
};
const result = await updateClubProfile(clubId, request);
if (result.success) {
setProfile(result.data);
setSuccess(true);
setError(null);
// Call parent update callback
if (onUpdate) {
onUpdate();
}
// Hide success message after 3 seconds
setTimeout(() => setSuccess(false), 3000);
} else {
// Handle validation errors
if (result.error.code === 'validation_error' && result.error.errors) {
const fieldErrors: Record = {};
result.error.errors.forEach(err => {
fieldErrors[err.field] = err.message;
});
setErrors(fieldErrors);
} else {
setError(result.error.detail);
}
}
setSaving(false);
}
function handleCancel() {
if (!profile) return;
// Reset form to original values - read from settings structure
setName(profile.name);
setTimezone(profile.timezone);
setAddressLine1(profile.settings?.address?.line_1 || '');
setAddressLine2(profile.settings?.address?.line_2 || '');
setCity(profile.settings?.address?.city || '');
setPostalCode(profile.settings?.address?.postal_code || '');
setCountry(profile.settings?.address?.country || '');
setPhone(profile.settings?.contact?.phone || '');
setEmail(profile.settings?.contact?.email || '');
setWebsite(profile.settings?.contact?.website || '');
setErrors({});
setError(null);
setEditingFields(new Set());
}
function toggleEditField(fieldName: string) {
setEditingFields(prev => {
const next = new Set(prev);
if (next.has(fieldName)) {
next.delete(fieldName);
} else {
next.add(fieldName);
}
return next;
});
}
function isFieldEditing(fieldName: string): boolean {
return editingFields.has(fieldName);
}
function hasFieldValue(value: string): boolean {
return value.trim().length > 0;
}
// Loading state
if (loading) {
return (
);
}
// Error state
if (error && !profile) {
return (
);
}
if (!profile) return null;
return (
{/* Success message */}
{success && (
Profile updated successfully
)}
{/* Error message */}
{error && (
)}
);
}