ui-nyla/src/components/Speech/SpeechSettings.tsx

482 lines
19 KiB
TypeScript

import React, { useState, useEffect } from 'react';
import { IoIosBusiness, IoIosContact, IoIosTime, IoIosRefresh } from 'react-icons/io';
import sharedStyles from '../PageManager/pages.module.css';
import styles from './SpeechSettings.module.css';
import { useLanguage } from '../../contexts/LanguageContext';
interface MandateData {
id: string;
mandate_general: {
company_name: string;
industry: string;
contact_info: {
email: string;
phone: string;
street: string;
postal_code: string;
city: string;
country: string;
};
business_hours: string;
timezone: string;
};
setup_contacts: boolean;
}
interface SpeechSettingsProps {
onDataUpdate?: (data: MandateData) => void;
}
function SpeechSettings({ onDataUpdate }: SpeechSettingsProps) {
const { t } = useLanguage();
const [formData, setFormData] = useState<MandateData | null>(null);
const [isLoading, setIsLoading] = useState(true);
const [isSaving, setIsSaving] = useState(false);
const [saveMessage, setSaveMessage] = useState<{ type: 'success' | 'error', text: string } | null>(null);
const [focusedFields, setFocusedFields] = useState<Set<string>>(new Set());
// Load data from localStorage on component mount
useEffect(() => {
const loadSpeechData = () => {
try {
const savedData = localStorage.getItem('speechSignUpData');
const timestamp = localStorage.getItem('speechSignUpTimestamp');
if (savedData && timestamp) {
const parsedData = JSON.parse(savedData);
const savedTime = parseInt(timestamp);
const now = Date.now();
const twentyFourHours = 24 * 60 * 60 * 1000;
// Check if data is still valid (within 24 hours)
if (now - savedTime < twentyFourHours) {
setFormData(parsedData);
} else {
// Data expired, clear it
localStorage.removeItem('speechSignUpData');
localStorage.removeItem('speechSignUpTimestamp');
}
}
} catch (error) {
console.error('Error loading speech data:', error);
} finally {
setIsLoading(false);
}
};
loadSpeechData();
}, []);
const handleInputChange = (field: string, value: string) => {
if (!formData) return;
const newData = { ...formData };
const fieldParts = field.split('.');
if (fieldParts.length === 2) {
// Handle nested fields like mandate_general.company_name
const [parent, child] = fieldParts;
if (parent === 'mandate_general' && child in newData.mandate_general) {
(newData.mandate_general as any)[child] = value;
}
} else if (fieldParts.length === 3) {
// Handle deeply nested fields like mandate_general.contact_info.email
const [parent, child, grandchild] = fieldParts;
if (parent === 'mandate_general' && child === 'contact_info' && grandchild in newData.mandate_general.contact_info) {
(newData.mandate_general.contact_info as any)[grandchild] = value;
}
} else if (field === 'setup_contacts') {
newData.setup_contacts = value === 'true';
}
setFormData(newData);
setSaveMessage(null);
};
const handleFocus = (field: string) => {
setFocusedFields(prev => new Set(prev).add(field));
};
const handleBlur = (field: string) => {
setFocusedFields(prev => {
const newSet = new Set(prev);
newSet.delete(field);
return newSet;
});
};
const handleSave = async () => {
if (!formData) return;
setIsSaving(true);
try {
// Save to localStorage
localStorage.setItem('speechSignUpData', JSON.stringify(formData));
localStorage.setItem('speechSignUpTimestamp', Date.now().toString());
// Dispatch event to notify other components
window.dispatchEvent(new CustomEvent('speechSignUpChanged'));
setSaveMessage({ type: 'success', text: t('speech.settings.save_success') });
// Notify parent component if callback provided
if (onDataUpdate) {
onDataUpdate(formData);
}
// Clear message after 3 seconds
setTimeout(() => setSaveMessage(null), 3000);
} catch (error) {
console.error('Error saving speech settings:', error);
setSaveMessage({ type: 'error', text: t('speech.settings.save_error') });
} finally {
setIsSaving(false);
}
};
const handleReset = () => {
if (window.confirm(t('speech.settings.reset_confirm'))) {
localStorage.removeItem('speechSignUpData');
localStorage.removeItem('speechSignUpTimestamp');
window.dispatchEvent(new CustomEvent('speechSignUpChanged'));
setFormData(null);
setSaveMessage({ type: 'success', text: t('speech.settings.reset_success') });
setTimeout(() => setSaveMessage(null), 3000);
}
};
if (isLoading) {
return (
<div className={styles.container}>
<div className={styles.loading}>
{t('common.loading')}
</div>
</div>
);
}
if (!formData) {
return (
<div className={styles.container}>
<div className={styles.noData}>
<p>{t('speech.settings.no_data')}</p>
<button
className={sharedStyles.primaryButton}
onClick={() => window.location.href = '/speech'}
>
{t('speech.settings.sign_up_now')}
</button>
</div>
</div>
);
}
return (
<div className={styles.container}>
<div className={styles.header}>
<h2 className={styles.title}>{t('speech.settings.title')}</h2>
<p className={styles.description}>{t('speech.settings.description')}</p>
</div>
{saveMessage && (
<div className={`${styles.message} ${saveMessage.type === 'success' ? styles.successMessage : styles.errorMessage}`}>
{saveMessage.text}
</div>
)}
<div className={styles.form}>
{/* Company Information Section */}
<div className={styles.section}>
<div className={styles.sectionHeader}>
<IoIosBusiness className={styles.sectionIcon} />
<h3 className={styles.sectionTitle}>{t('speech.settings.company_info')}</h3>
</div>
<div className={styles.formRow}>
<div className={styles.formField}>
<div className={styles.inputContainer}>
<input
type="text"
id="company_name"
className={styles.formInput}
value={formData.mandate_general.company_name}
onChange={(e) => handleInputChange('mandate_general.company_name', e.target.value)}
onFocus={() => handleFocus('company_name')}
onBlur={() => handleBlur('company_name')}
required
/>
<label
htmlFor="company_name"
className={`${styles.floatingLabel} ${formData.mandate_general.company_name || focusedFields.has('company_name') ? styles.floatingLabelActive : ''}`}
>
{t('speech.signup.company_name')} *
</label>
</div>
</div>
<div className={styles.formField}>
<div className={styles.inputContainer}>
<input
type="text"
id="industry"
className={styles.formInput}
value={formData.mandate_general.industry}
onChange={(e) => handleInputChange('mandate_general.industry', e.target.value)}
onFocus={() => handleFocus('industry')}
onBlur={() => handleBlur('industry')}
required
/>
<label
htmlFor="industry"
className={`${styles.floatingLabel} ${formData.mandate_general.industry || focusedFields.has('industry') ? styles.floatingLabelActive : ''}`}
>
{t('speech.signup.industry')} *
</label>
</div>
</div>
</div>
</div>
{/* Contact Information Section */}
<div className={styles.section}>
<div className={styles.sectionHeader}>
<IoIosContact className={styles.sectionIcon} />
<h3 className={styles.sectionTitle}>{t('speech.settings.contact_info')}</h3>
</div>
<div className={styles.formRow}>
<div className={styles.formField}>
<div className={styles.inputContainer}>
<input
type="email"
id="email"
className={styles.formInput}
value={formData.mandate_general.contact_info.email}
onChange={(e) => handleInputChange('mandate_general.contact_info.email', e.target.value)}
onFocus={() => handleFocus('email')}
onBlur={() => handleBlur('email')}
required
/>
<label
htmlFor="email"
className={`${styles.floatingLabel} ${formData.mandate_general.contact_info.email || focusedFields.has('email') ? styles.floatingLabelActive : ''}`}
>
{t('speech.signup.email')} *
</label>
</div>
</div>
<div className={styles.formField}>
<div className={styles.inputContainer}>
<input
type="tel"
id="phone"
className={styles.formInput}
value={formData.mandate_general.contact_info.phone}
onChange={(e) => handleInputChange('mandate_general.contact_info.phone', e.target.value)}
onFocus={() => handleFocus('phone')}
onBlur={() => handleBlur('phone')}
required
/>
<label
htmlFor="phone"
className={`${styles.floatingLabel} ${formData.mandate_general.contact_info.phone || focusedFields.has('phone') ? styles.floatingLabelActive : ''}`}
>
{t('speech.signup.phone')} *
</label>
</div>
</div>
</div>
<div className={styles.formRow}>
<div className={styles.formField}>
<div className={styles.inputContainer}>
<input
type="text"
id="street"
className={styles.formInput}
value={formData.mandate_general.contact_info.street}
onChange={(e) => handleInputChange('mandate_general.contact_info.street', e.target.value)}
onFocus={() => handleFocus('street')}
onBlur={() => handleBlur('street')}
required
/>
<label
htmlFor="street"
className={`${styles.floatingLabel} ${formData.mandate_general.contact_info.street || focusedFields.has('street') ? styles.floatingLabelActive : ''}`}
>
{t('speech.signup.street')} *
</label>
</div>
</div>
<div className={styles.formField}>
<div className={styles.inputContainer}>
<input
type="text"
id="postal_code"
className={styles.formInput}
value={formData.mandate_general.contact_info.postal_code}
onChange={(e) => handleInputChange('mandate_general.contact_info.postal_code', e.target.value)}
onFocus={() => handleFocus('postal_code')}
onBlur={() => handleBlur('postal_code')}
required
/>
<label
htmlFor="postal_code"
className={`${styles.floatingLabel} ${formData.mandate_general.contact_info.postal_code || focusedFields.has('postal_code') ? styles.floatingLabelActive : ''}`}
>
{t('speech.signup.postal_code')} *
</label>
</div>
</div>
</div>
<div className={styles.formRow}>
<div className={styles.formField}>
<div className={styles.inputContainer}>
<input
type="text"
id="city"
className={styles.formInput}
value={formData.mandate_general.contact_info.city}
onChange={(e) => handleInputChange('mandate_general.contact_info.city', e.target.value)}
onFocus={() => handleFocus('city')}
onBlur={() => handleBlur('city')}
required
/>
<label
htmlFor="city"
className={`${styles.floatingLabel} ${formData.mandate_general.contact_info.city || focusedFields.has('city') ? styles.floatingLabelActive : ''}`}
>
{t('speech.signup.city')} *
</label>
</div>
</div>
<div className={styles.formField}>
<div className={styles.inputContainer}>
<input
type="text"
id="country"
className={styles.formInput}
value={formData.mandate_general.contact_info.country}
onChange={(e) => handleInputChange('mandate_general.contact_info.country', e.target.value)}
onFocus={() => handleFocus('country')}
onBlur={() => handleBlur('country')}
required
/>
<label
htmlFor="country"
className={`${styles.floatingLabel} ${formData.mandate_general.contact_info.country || focusedFields.has('country') ? styles.floatingLabelActive : ''}`}
>
{t('speech.signup.country')} *
</label>
</div>
</div>
</div>
</div>
{/* Business Hours Section */}
<div className={styles.section}>
<div className={styles.sectionHeader}>
<IoIosTime className={styles.sectionIcon} />
<h3 className={styles.sectionTitle}>{t('speech.settings.business_hours')}</h3>
</div>
<div className={styles.formRow}>
<div className={styles.formField}>
<div className={styles.inputContainer}>
<input
type="text"
id="business_hours"
className={styles.formInput}
value={formData.mandate_general.business_hours}
onChange={(e) => handleInputChange('mandate_general.business_hours', e.target.value)}
onFocus={() => handleFocus('business_hours')}
onBlur={() => handleBlur('business_hours')}
required
/>
<label
htmlFor="business_hours"
className={`${styles.floatingLabel} ${formData.mandate_general.business_hours || focusedFields.has('business_hours') ? styles.floatingLabelActive : ''}`}
>
{t('speech.signup.business_hours')} *
</label>
</div>
</div>
<div className={styles.formField}>
<div className={styles.inputContainer}>
<select
id="timezone"
className={styles.formSelect}
value={formData.mandate_general.timezone}
onChange={(e) => handleInputChange('mandate_general.timezone', e.target.value)}
onFocus={() => handleFocus('timezone')}
onBlur={() => handleBlur('timezone')}
required
>
<option value="">{t('speech.signup.select_timezone')}</option>
<option value="UTC-12">UTC-12 (Baker Island)</option>
<option value="UTC-11">UTC-11 (American Samoa)</option>
<option value="UTC-10">UTC-10 (Hawaii)</option>
<option value="UTC-9">UTC-9 (Alaska)</option>
<option value="UTC-8">UTC-8 (Pacific Time)</option>
<option value="UTC-7">UTC-7 (Mountain Time)</option>
<option value="UTC-6">UTC-6 (Central Time)</option>
<option value="UTC-5">UTC-5 (Eastern Time)</option>
<option value="UTC-4">UTC-4 (Atlantic Time)</option>
<option value="UTC-3">UTC-3 (Brazil)</option>
<option value="UTC-2">UTC-2 (Mid-Atlantic)</option>
<option value="UTC-1">UTC-1 (Azores)</option>
<option value="UTC+0">UTC+0 (Greenwich Mean Time)</option>
<option value="UTC+1">UTC+1 (Central European Time)</option>
<option value="UTC+2">UTC+2 (Eastern European Time)</option>
<option value="UTC+3">UTC+3 (Moscow Time)</option>
<option value="UTC+4">UTC+4 (Gulf Standard Time)</option>
<option value="UTC+5">UTC+5 (Pakistan Standard Time)</option>
<option value="UTC+6">UTC+6 (Bangladesh Standard Time)</option>
<option value="UTC+7">UTC+7 (Indochina Time)</option>
<option value="UTC+8">UTC+8 (China Standard Time)</option>
<option value="UTC+9">UTC+9 (Japan Standard Time)</option>
<option value="UTC+10">UTC+10 (Australian Eastern Time)</option>
<option value="UTC+11">UTC+11 (Solomon Islands)</option>
<option value="UTC+12">UTC+12 (New Zealand)</option>
</select>
<label
htmlFor="timezone"
className={`${styles.floatingLabel} ${formData.mandate_general.timezone || focusedFields.has('timezone') ? styles.floatingLabelActive : ''}`}
>
{t('speech.signup.timezone')} *
</label>
</div>
</div>
</div>
</div>
{/* Actions */}
<div className={styles.actions}>
<button
className={sharedStyles.secondaryButton}
onClick={handleReset}
disabled={isSaving}
>
<IoIosRefresh className={styles.resetIcon} />
{t('speech.settings.reset')}
</button>
<button
className={sharedStyles.primaryButton}
onClick={handleSave}
disabled={isSaving}
>
{isSaving ? t('speech.settings.saving') : t('speech.settings.save')}
</button>
</div>
</div>
</div>
);
}
export default SpeechSettings;