fix:deleted legacy code
This commit is contained in:
parent
a06fe0c793
commit
322ab7b890
11 changed files with 0 additions and 2571 deletions
|
|
@ -1,331 +0,0 @@
|
||||||
.container {
|
|
||||||
max-width: 100%;
|
|
||||||
margin: 0;
|
|
||||||
padding: 1.5rem;
|
|
||||||
text-align: center;
|
|
||||||
height: calc(100vh - 120px);
|
|
||||||
overflow-y: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.content {
|
|
||||||
background: var(--color-bg);
|
|
||||||
padding: 2rem;
|
|
||||||
border-radius: 25px;
|
|
||||||
border: 1px solid var(--color-secondary);
|
|
||||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
|
|
||||||
margin-bottom: 1.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.iconContainer {
|
|
||||||
margin-bottom: 2rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.successIcon {
|
|
||||||
font-size: 4rem;
|
|
||||||
color: var(--color-secondary);
|
|
||||||
}
|
|
||||||
|
|
||||||
.title {
|
|
||||||
font-size: 1.8rem;
|
|
||||||
font-weight: bold;
|
|
||||||
margin: 0 0 1rem 0;
|
|
||||||
color: var(--color-text);
|
|
||||||
}
|
|
||||||
|
|
||||||
.message {
|
|
||||||
font-size: 1rem;
|
|
||||||
color: var(--color-text);
|
|
||||||
line-height: 1.6;
|
|
||||||
margin-bottom: 2rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.nextSteps {
|
|
||||||
text-align: left;
|
|
||||||
margin-bottom: 2rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.nextSteps h2 {
|
|
||||||
font-size: 1.2rem;
|
|
||||||
font-weight: bold;
|
|
||||||
margin: 0 0 1.5rem 0;
|
|
||||||
color: var(--color-secondary);
|
|
||||||
text-align: center;
|
|
||||||
padding-bottom: 0.5rem;
|
|
||||||
border-bottom: 2px solid var(--color-secondary);
|
|
||||||
}
|
|
||||||
|
|
||||||
.step {
|
|
||||||
display: flex;
|
|
||||||
align-items: flex-start;
|
|
||||||
gap: 1rem;
|
|
||||||
margin-bottom: 1.5rem;
|
|
||||||
padding: 1.25rem;
|
|
||||||
background: var(--color-bg);
|
|
||||||
border-radius: 20px;
|
|
||||||
border: 1px solid var(--color-secondary);
|
|
||||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
|
|
||||||
}
|
|
||||||
|
|
||||||
.stepIcon {
|
|
||||||
flex-shrink: 0;
|
|
||||||
width: 40px;
|
|
||||||
height: 40px;
|
|
||||||
background: var(--color-secondary);
|
|
||||||
border-radius: 50%;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.stepIconInner {
|
|
||||||
color: white;
|
|
||||||
font-size: 1.2rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.stepContent h3 {
|
|
||||||
font-size: 1rem;
|
|
||||||
font-weight: bold;
|
|
||||||
margin: 0 0 0.5rem 0;
|
|
||||||
color: var(--color-text);
|
|
||||||
}
|
|
||||||
|
|
||||||
.stepContent p {
|
|
||||||
color: var(--color-text);
|
|
||||||
margin: 0;
|
|
||||||
line-height: 1.5;
|
|
||||||
}
|
|
||||||
|
|
||||||
.contactInfo {
|
|
||||||
background: var(--color-bg);
|
|
||||||
padding: 1.5rem;
|
|
||||||
border-radius: 20px;
|
|
||||||
border: 1px solid var(--color-secondary);
|
|
||||||
text-align: left;
|
|
||||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
|
|
||||||
}
|
|
||||||
|
|
||||||
.contactInfo h3 {
|
|
||||||
font-size: 1.1rem;
|
|
||||||
font-weight: bold;
|
|
||||||
margin: 0 0 0.5rem 0;
|
|
||||||
color: var(--color-secondary);
|
|
||||||
text-align: center;
|
|
||||||
padding-bottom: 0.5rem;
|
|
||||||
border-bottom: 2px solid var(--color-secondary);
|
|
||||||
}
|
|
||||||
|
|
||||||
.contactInfo p {
|
|
||||||
color: var(--color-text);
|
|
||||||
margin: 0 0 1rem 0;
|
|
||||||
line-height: 1.5;
|
|
||||||
}
|
|
||||||
|
|
||||||
.contactMethods {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
gap: 0.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.contactMethod {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 0.5rem;
|
|
||||||
color: var(--color-text);
|
|
||||||
}
|
|
||||||
|
|
||||||
.contactIcon {
|
|
||||||
color: var(--color-secondary);
|
|
||||||
font-size: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.submittedData {
|
|
||||||
background: var(--color-bg);
|
|
||||||
padding: 1.5rem;
|
|
||||||
border-radius: 20px;
|
|
||||||
border: 1px solid var(--color-secondary);
|
|
||||||
margin-bottom: 2rem;
|
|
||||||
text-align: left;
|
|
||||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
|
|
||||||
}
|
|
||||||
|
|
||||||
.submittedData h3 {
|
|
||||||
font-size: 1.1rem;
|
|
||||||
font-weight: bold;
|
|
||||||
margin: 0 0 1rem 0;
|
|
||||||
color: var(--color-secondary);
|
|
||||||
text-align: center;
|
|
||||||
padding-bottom: 0.5rem;
|
|
||||||
border-bottom: 2px solid var(--color-secondary);
|
|
||||||
}
|
|
||||||
|
|
||||||
.dataGrid {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
|
|
||||||
gap: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dataItem {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
gap: 0.25rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dataItem strong {
|
|
||||||
color: var(--color-text);
|
|
||||||
font-size: 0.9rem;
|
|
||||||
font-weight: 600;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dataItem span {
|
|
||||||
color: var(--color-text);
|
|
||||||
font-size: 0.9rem;
|
|
||||||
word-break: break-word;
|
|
||||||
}
|
|
||||||
|
|
||||||
.actions {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
gap: 1rem;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
.backButton {
|
|
||||||
padding: 8px 16px;
|
|
||||||
border: 1px solid var(--color-primary);
|
|
||||||
background-color: var(--color-bg);
|
|
||||||
color: var(--color-text);
|
|
||||||
border-radius: 25px;
|
|
||||||
font-size: 14px;
|
|
||||||
font-weight: 500;
|
|
||||||
cursor: pointer;
|
|
||||||
transition: all 0.2s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.backButton:hover {
|
|
||||||
background-color: var(--color-primary-hover);
|
|
||||||
border-color: var(--color-primary);
|
|
||||||
color: #181818;
|
|
||||||
}
|
|
||||||
|
|
||||||
.resetButton {
|
|
||||||
padding: 8px 16px;
|
|
||||||
border: none;
|
|
||||||
background-color: var(--color-secondary);
|
|
||||||
color: var(--color-bg);
|
|
||||||
border-radius: 25px;
|
|
||||||
font-size: 14px;
|
|
||||||
font-weight: 500;
|
|
||||||
cursor: pointer;
|
|
||||||
transition: all 0.2s ease;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 0.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.resetButton:hover {
|
|
||||||
background-color: var(--color-secondary-hover);
|
|
||||||
}
|
|
||||||
|
|
||||||
.resetIcon {
|
|
||||||
font-size: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.additionalActions {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
gap: 1rem;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
margin-top: 1.5rem;
|
|
||||||
padding-top: 1.5rem;
|
|
||||||
border-top: 1px solid var(--color-secondary);
|
|
||||||
}
|
|
||||||
|
|
||||||
.transcriptButton {
|
|
||||||
padding: 8px 16px;
|
|
||||||
border: none;
|
|
||||||
background-color: var(--color-secondary);
|
|
||||||
color: var(--color-bg);
|
|
||||||
border-radius: 25px;
|
|
||||||
font-size: 14px;
|
|
||||||
font-weight: 500;
|
|
||||||
cursor: pointer;
|
|
||||||
transition: all 0.2s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.transcriptButton:hover {
|
|
||||||
background-color: var(--color-secondary-hover);
|
|
||||||
}
|
|
||||||
|
|
||||||
.settingsButton {
|
|
||||||
padding: 8px 16px;
|
|
||||||
border: 1px solid var(--color-primary);
|
|
||||||
background-color: var(--color-bg);
|
|
||||||
color: var(--color-text);
|
|
||||||
border-radius: 25px;
|
|
||||||
font-size: 14px;
|
|
||||||
font-weight: 500;
|
|
||||||
cursor: pointer;
|
|
||||||
transition: all 0.2s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.settingsButton:hover {
|
|
||||||
background-color: var(--color-primary-hover);
|
|
||||||
border-color: var(--color-primary);
|
|
||||||
color: #181818;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: 640px) {
|
|
||||||
.container {
|
|
||||||
padding: 1rem;
|
|
||||||
height: calc(100vh - 100px);
|
|
||||||
}
|
|
||||||
|
|
||||||
.content {
|
|
||||||
padding: 1.5rem 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.title {
|
|
||||||
font-size: 1.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.step {
|
|
||||||
flex-direction: column;
|
|
||||||
text-align: center;
|
|
||||||
padding: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.stepIcon {
|
|
||||||
align-self: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.contactMethods {
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dataGrid {
|
|
||||||
grid-template-columns: 1fr;
|
|
||||||
gap: 0.75rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.actions {
|
|
||||||
flex-direction: column-reverse;
|
|
||||||
}
|
|
||||||
|
|
||||||
.backButton,
|
|
||||||
.resetButton {
|
|
||||||
width: 100%;
|
|
||||||
padding: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.additionalActions {
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.transcriptButton,
|
|
||||||
.settingsButton {
|
|
||||||
width: 100%;
|
|
||||||
max-width: 200px;
|
|
||||||
padding: 12px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,170 +0,0 @@
|
||||||
import { IoIosCheckmarkCircle, IoIosMail, IoIosCall, IoIosTime, IoIosRefresh } from 'react-icons/io';
|
|
||||||
import { useNavigate } from 'react-router-dom';
|
|
||||||
import sharedStyles from '../../core/PageManager/pages.module.css';
|
|
||||||
import styles from './SpeechConfirmation.module.css';
|
|
||||||
import { useLanguage } from '../../providers/language/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 SpeechConfirmationProps {
|
|
||||||
onBackToInfo: () => void;
|
|
||||||
submittedData?: MandateData | null;
|
|
||||||
onReset?: () => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
function SpeechConfirmation({ onBackToInfo, submittedData, onReset }: SpeechConfirmationProps) {
|
|
||||||
const { t } = useLanguage();
|
|
||||||
const navigate = useNavigate();
|
|
||||||
return (
|
|
||||||
<div className={styles.container}>
|
|
||||||
<div className={styles.content}>
|
|
||||||
<div className={styles.iconContainer}>
|
|
||||||
<IoIosCheckmarkCircle className={styles.successIcon} />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<h1 className={styles.title}>{t('speech.confirmation.title')}</h1>
|
|
||||||
|
|
||||||
<p className={styles.message}>
|
|
||||||
{t('speech.confirmation.message')}
|
|
||||||
</p>
|
|
||||||
|
|
||||||
{submittedData && (
|
|
||||||
<div className={styles.submittedData}>
|
|
||||||
<h3>{t('speech.confirmation.submitted_data')}</h3>
|
|
||||||
<div className={styles.dataGrid}>
|
|
||||||
<div className={styles.dataItem}>
|
|
||||||
<strong>{t('speech.confirmation.company')}:</strong>
|
|
||||||
<span>{submittedData.mandate_general.company_name}</span>
|
|
||||||
</div>
|
|
||||||
<div className={styles.dataItem}>
|
|
||||||
<strong>{t('speech.confirmation.industry')}:</strong>
|
|
||||||
<span>{submittedData.mandate_general.industry}</span>
|
|
||||||
</div>
|
|
||||||
<div className={styles.dataItem}>
|
|
||||||
<strong>{t('speech.confirmation.email')}:</strong>
|
|
||||||
<span>{submittedData.mandate_general.contact_info.email}</span>
|
|
||||||
</div>
|
|
||||||
<div className={styles.dataItem}>
|
|
||||||
<strong>{t('speech.confirmation.phone')}:</strong>
|
|
||||||
<span>{submittedData.mandate_general.contact_info.phone}</span>
|
|
||||||
</div>
|
|
||||||
<div className={styles.dataItem}>
|
|
||||||
<strong>{t('speech.confirmation.address')}:</strong>
|
|
||||||
<span>
|
|
||||||
{submittedData.mandate_general.contact_info.street}, {submittedData.mandate_general.contact_info.postal_code} {submittedData.mandate_general.contact_info.city}, {submittedData.mandate_general.contact_info.country}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div className={styles.dataItem}>
|
|
||||||
<strong>{t('speech.confirmation.timezone')}:</strong>
|
|
||||||
<span>{submittedData.mandate_general.timezone}</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<div className={styles.nextSteps}>
|
|
||||||
<h2>{t('speech.confirmation.next_steps')}</h2>
|
|
||||||
|
|
||||||
<div className={styles.step}>
|
|
||||||
<div className={styles.stepIcon}>
|
|
||||||
<IoIosMail className={styles.stepIconInner} />
|
|
||||||
</div>
|
|
||||||
<div className={styles.stepContent}>
|
|
||||||
<h3>{t('speech.confirmation.email_confirmation')}</h3>
|
|
||||||
<p>{t('speech.confirmation.email_confirmation_desc')}</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className={styles.step}>
|
|
||||||
<div className={styles.stepIcon}>
|
|
||||||
<IoIosTime className={styles.stepIconInner} />
|
|
||||||
</div>
|
|
||||||
<div className={styles.stepContent}>
|
|
||||||
<h3>{t('speech.confirmation.review_process')}</h3>
|
|
||||||
<p>{t('speech.confirmation.review_process_desc')}</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className={styles.step}>
|
|
||||||
<div className={styles.stepIcon}>
|
|
||||||
<IoIosCall className={styles.stepIconInner} />
|
|
||||||
</div>
|
|
||||||
<div className={styles.stepContent}>
|
|
||||||
<h3>{t('speech.confirmation.setup_call')}</h3>
|
|
||||||
<p>{t('speech.confirmation.setup_call_desc')}</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className={styles.contactInfo}>
|
|
||||||
<h3>{t('speech.confirmation.questions')}</h3>
|
|
||||||
<p>
|
|
||||||
{t('speech.confirmation.questions_desc')}
|
|
||||||
</p>
|
|
||||||
<div className={styles.contactMethods}>
|
|
||||||
<div className={styles.contactMethod}>
|
|
||||||
<IoIosMail className={styles.contactIcon} />
|
|
||||||
<span>support@spitch.ai</span>
|
|
||||||
</div>
|
|
||||||
<div className={styles.contactMethod}>
|
|
||||||
<IoIosCall className={styles.contactIcon} />
|
|
||||||
<span>+1 (555) 123-4567</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className={styles.actions}>
|
|
||||||
<button
|
|
||||||
className={`${sharedStyles.secondaryButton} ${styles.backButton}`}
|
|
||||||
onClick={onBackToInfo}
|
|
||||||
>
|
|
||||||
{t('speech.confirmation.back')}
|
|
||||||
</button>
|
|
||||||
{onReset && (
|
|
||||||
<button
|
|
||||||
className={`${sharedStyles.primaryButton} ${styles.resetButton}`}
|
|
||||||
onClick={onReset}
|
|
||||||
>
|
|
||||||
<IoIosRefresh className={styles.resetIcon} />
|
|
||||||
{t('speech.confirmation.reset')}
|
|
||||||
</button>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className={styles.additionalActions}>
|
|
||||||
<button
|
|
||||||
className={`${sharedStyles.primaryButton} ${styles.transcriptButton}`}
|
|
||||||
onClick={() => navigate('/speech/transcripts')}
|
|
||||||
>
|
|
||||||
{t('speech.confirmation.transcript_management')}
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
className={`${sharedStyles.secondaryButton} ${styles.settingsButton}`}
|
|
||||||
onClick={() => navigate('/einstellungen#speech-settings')}
|
|
||||||
>
|
|
||||||
{t('speech.confirmation.speech_settings')}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default SpeechConfirmation;
|
|
||||||
|
|
@ -1,283 +0,0 @@
|
||||||
.container {
|
|
||||||
margin: 0 auto;
|
|
||||||
text-align: center;
|
|
||||||
width: 100%;
|
|
||||||
margin: 0;
|
|
||||||
height: 100%;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: space-between;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
.content {
|
|
||||||
flex: 1;
|
|
||||||
width: 100%;
|
|
||||||
margin: 0;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: space-between;
|
|
||||||
min-height: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.features {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: repeat(3, 1fr);
|
|
||||||
gap: 1rem;
|
|
||||||
margin-bottom: 1rem;
|
|
||||||
flex: 1;
|
|
||||||
min-height: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.feature {
|
|
||||||
padding: 1rem;
|
|
||||||
border-radius: 20px;
|
|
||||||
background: var(--color-bg);
|
|
||||||
border: 1px solid var(--color-secondary);
|
|
||||||
transition: all 0.3s ease;
|
|
||||||
color: var(--color-text);
|
|
||||||
position: relative;
|
|
||||||
overflow: hidden;
|
|
||||||
min-height: 160px;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.feature::before {
|
|
||||||
content: '';
|
|
||||||
position: absolute;
|
|
||||||
bottom: 0;
|
|
||||||
right: 0;
|
|
||||||
width: 60px;
|
|
||||||
height: 60px;
|
|
||||||
background: linear-gradient(135deg, var(--color-secondary), transparent 50%);
|
|
||||||
opacity: 0.1;
|
|
||||||
border-radius: 50% 0 0 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.feature:hover {
|
|
||||||
transform: translateY(-8px);
|
|
||||||
box-shadow: 0 12px 24px rgba(0, 0, 0, 0.15);
|
|
||||||
background: var(--color-secondary);
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
.feature:hover::before {
|
|
||||||
opacity: 0.2;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
.featureIconContainer {
|
|
||||||
width: 50px;
|
|
||||||
height: 50px;
|
|
||||||
border-radius: 50%;
|
|
||||||
background: var(--feature-color, #ff4757);
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
margin-bottom: 0.75rem;
|
|
||||||
transition: all 0.3s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.feature:hover .featureIconContainer {
|
|
||||||
background: white;
|
|
||||||
transform: scale(1.1);
|
|
||||||
}
|
|
||||||
|
|
||||||
.featureAcronym {
|
|
||||||
font-size: 1.2rem;
|
|
||||||
font-weight: bold;
|
|
||||||
color: white;
|
|
||||||
letter-spacing: 1px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.feature:hover .featureAcronym {
|
|
||||||
color: var(--feature-color, #ff4757);
|
|
||||||
}
|
|
||||||
|
|
||||||
.featureTitle {
|
|
||||||
font-size: 1rem;
|
|
||||||
font-weight: bold;
|
|
||||||
margin: 0 0 0.5rem 0;
|
|
||||||
color: var(--color-text);
|
|
||||||
transition: color 0.3s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.feature:hover .featureTitle {
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
.featureDescription {
|
|
||||||
color: var(--color-text-secondary);
|
|
||||||
margin: 0;
|
|
||||||
line-height: 1.3;
|
|
||||||
font-size: 0.8rem;
|
|
||||||
transition: color 0.3s ease;
|
|
||||||
flex-grow: 1;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.feature:hover .featureDescription {
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
.partnerInfo {
|
|
||||||
background: var(--color-bg);
|
|
||||||
padding: 1rem;
|
|
||||||
border-radius: 20px;
|
|
||||||
border: 1px solid var(--color-secondary);
|
|
||||||
text-align: left;
|
|
||||||
margin-bottom: 0.5rem;
|
|
||||||
flex-shrink: 0;
|
|
||||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
|
|
||||||
}
|
|
||||||
|
|
||||||
.partnerInfo h2 {
|
|
||||||
font-size: 1.1rem;
|
|
||||||
font-weight: bold;
|
|
||||||
color: var(--color-secondary);
|
|
||||||
margin: 0 0 0.75rem 0;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.introText {
|
|
||||||
color: var(--color-text);
|
|
||||||
line-height: 1.4;
|
|
||||||
margin-bottom: 1rem;
|
|
||||||
font-size: 0.85rem;
|
|
||||||
text-align: center;
|
|
||||||
font-style: italic;
|
|
||||||
}
|
|
||||||
|
|
||||||
.featureSection {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: repeat(2, 1fr);
|
|
||||||
gap: 0.75rem;
|
|
||||||
margin-bottom: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.featureItem {
|
|
||||||
background: var(--color-secondary);
|
|
||||||
padding: 0.75rem;
|
|
||||||
border-radius: 10px;
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
.featureItem h3 {
|
|
||||||
font-size: 0.8rem;
|
|
||||||
font-weight: bold;
|
|
||||||
margin: 0 0 0.4rem 0;
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
.featureItem p {
|
|
||||||
font-size: 0.7rem;
|
|
||||||
line-height: 1.3;
|
|
||||||
margin: 0;
|
|
||||||
color: rgba(255, 255, 255, 0.9);
|
|
||||||
}
|
|
||||||
|
|
||||||
.partnerLink {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 0.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.linkIcon {
|
|
||||||
color: var(--color-secondary);
|
|
||||||
}
|
|
||||||
|
|
||||||
.partnerLink a {
|
|
||||||
color: var(--color-secondary);
|
|
||||||
text-decoration: none;
|
|
||||||
font-weight: 500;
|
|
||||||
transition: color 0.2s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.partnerLink a:hover {
|
|
||||||
color: var(--primary-hover, #0056b3);
|
|
||||||
text-decoration: underline;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@media (max-width: 1024px) {
|
|
||||||
.features {
|
|
||||||
grid-template-columns: repeat(2, 1fr);
|
|
||||||
gap: 0.75rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.feature {
|
|
||||||
min-height: 140px;
|
|
||||||
padding: 0.75rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: 768px) {
|
|
||||||
.container {
|
|
||||||
padding: 0.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
.features {
|
|
||||||
grid-template-columns: 1fr;
|
|
||||||
gap: 0.75rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.feature {
|
|
||||||
padding: 0.75rem;
|
|
||||||
min-height: 120px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.featureIconContainer {
|
|
||||||
width: 40px;
|
|
||||||
height: 40px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.featureAcronym {
|
|
||||||
font-size: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.featureTitle {
|
|
||||||
font-size: 0.9rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.featureDescription {
|
|
||||||
font-size: 0.75rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.partnerInfo {
|
|
||||||
padding: 0.75rem;
|
|
||||||
margin-bottom: 0.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.partnerInfo h2 {
|
|
||||||
font-size: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.introText {
|
|
||||||
font-size: 0.8rem;
|
|
||||||
margin-bottom: 0.75rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.featureSection {
|
|
||||||
grid-template-columns: 1fr;
|
|
||||||
gap: 0.5rem;
|
|
||||||
margin-bottom: 0.75rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.featureItem {
|
|
||||||
padding: 0.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.featureItem h3 {
|
|
||||||
font-size: 0.75rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.featureItem p {
|
|
||||||
font-size: 0.65rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,112 +0,0 @@
|
||||||
import { IoIosLink, IoIosCall, IoIosAnalytics, IoIosFingerPrint, IoIosBook, IoIosChatbubbles, IoIosDesktop } from 'react-icons/io';
|
|
||||||
import styles from './SpeechInfo.module.css';
|
|
||||||
import { useLanguage } from '../../providers/language/LanguageContext';
|
|
||||||
|
|
||||||
function SpeechInfo() {
|
|
||||||
const { t } = useLanguage();
|
|
||||||
|
|
||||||
const features = [
|
|
||||||
{
|
|
||||||
key: 'va',
|
|
||||||
icon: IoIosCall,
|
|
||||||
title: t('speech.info.va'),
|
|
||||||
description: t('speech.info.va_description'),
|
|
||||||
color: 'var(--color-secondary)'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'sa',
|
|
||||||
icon: IoIosAnalytics,
|
|
||||||
title: t('speech.info.sa'),
|
|
||||||
description: t('speech.info.sa_description'),
|
|
||||||
color: 'var(--color-secondary)'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'vb',
|
|
||||||
icon: IoIosFingerPrint,
|
|
||||||
title: t('speech.info.vb'),
|
|
||||||
description: t('speech.info.vb_description'),
|
|
||||||
color: 'var(--color-secondary)'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'ka',
|
|
||||||
icon: IoIosBook,
|
|
||||||
title: t('speech.info.ka'),
|
|
||||||
description: t('speech.info.ka_description'),
|
|
||||||
color: 'var(--color-secondary)'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'cp',
|
|
||||||
icon: IoIosChatbubbles,
|
|
||||||
title: t('speech.info.cp'),
|
|
||||||
description: t('speech.info.cp_description'),
|
|
||||||
color: 'var(--color-secondary)'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'aa',
|
|
||||||
icon: IoIosDesktop,
|
|
||||||
title: t('speech.info.aa'),
|
|
||||||
description: t('speech.info.aa_description'),
|
|
||||||
color: 'var(--color-secondary)'
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className={styles.container}>
|
|
||||||
<div className={styles.content}>
|
|
||||||
<div className={styles.features}>
|
|
||||||
{features.map((feature) => (
|
|
||||||
<div
|
|
||||||
key={feature.key}
|
|
||||||
className={`${styles.feature}`}
|
|
||||||
style={{ '--feature-color': feature.color } as React.CSSProperties}
|
|
||||||
>
|
|
||||||
<div className={styles.featureIconContainer}>
|
|
||||||
<span className={styles.featureAcronym}>{feature.key.toUpperCase()}</span>
|
|
||||||
</div>
|
|
||||||
<h3 className={styles.featureTitle}>{feature.title}</h3>
|
|
||||||
<p className={styles.featureDescription}>{feature.description}</p>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className={styles.partnerInfo}>
|
|
||||||
<h2>{t('speech.info.about')}</h2>
|
|
||||||
<p className={styles.introText}>
|
|
||||||
{t('speech.info.about_intro')}
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<div className={styles.featureSection}>
|
|
||||||
<div className={styles.featureItem}>
|
|
||||||
<h3>🎯 {t('speech.info.workflow_title')}</h3>
|
|
||||||
<p>{t('speech.info.workflow_description')}</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className={styles.featureItem}>
|
|
||||||
<h3>🤖 {t('speech.info.ai_title')}</h3>
|
|
||||||
<p>{t('speech.info.ai_description')}</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className={styles.featureItem}>
|
|
||||||
<h3>🔄 {t('speech.info.sync_title')}</h3>
|
|
||||||
<p>{t('speech.info.sync_description')}</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className={styles.featureItem}>
|
|
||||||
<h3>💰 {t('speech.info.cost_title')}</h3>
|
|
||||||
<p>{t('speech.info.cost_description')}</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className={styles.partnerLink}>
|
|
||||||
<IoIosLink className={styles.linkIcon} />
|
|
||||||
<a href="https://spitch.ai" target="_blank" rel="noopener noreferrer">
|
|
||||||
{t('speech.info.about_link')}
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default SpeechInfo;
|
|
||||||
|
|
@ -1,225 +0,0 @@
|
||||||
.container {
|
|
||||||
width: 100%;
|
|
||||||
max-width: 100%;
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.header {
|
|
||||||
margin-bottom: 2rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.title {
|
|
||||||
font-size: 1.5rem;
|
|
||||||
font-weight: 600;
|
|
||||||
color: var(--color-text);
|
|
||||||
margin: 0 0 0.5rem 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.description {
|
|
||||||
font-size: 1rem;
|
|
||||||
color: var(--color-text-secondary);
|
|
||||||
margin: 0;
|
|
||||||
line-height: 1.5;
|
|
||||||
}
|
|
||||||
|
|
||||||
.loading {
|
|
||||||
text-align: center;
|
|
||||||
padding: 2rem;
|
|
||||||
color: var(--color-text);
|
|
||||||
font-size: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.noData {
|
|
||||||
text-align: center;
|
|
||||||
padding: 2rem;
|
|
||||||
background: var(--color-bg);
|
|
||||||
border-radius: 20px;
|
|
||||||
border: 1px solid var(--color-secondary);
|
|
||||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
|
|
||||||
}
|
|
||||||
|
|
||||||
.noData p {
|
|
||||||
margin: 0 0 1.5rem 0;
|
|
||||||
color: var(--color-text);
|
|
||||||
font-size: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.message {
|
|
||||||
padding: 1rem;
|
|
||||||
border-radius: 8px;
|
|
||||||
margin-bottom: 1.5rem;
|
|
||||||
font-size: 0.9rem;
|
|
||||||
font-weight: 500;
|
|
||||||
}
|
|
||||||
|
|
||||||
.successMessage {
|
|
||||||
background-color: rgba(34, 197, 94, 0.1);
|
|
||||||
color: #16a34a;
|
|
||||||
border: 1px solid rgba(34, 197, 94, 0.2);
|
|
||||||
}
|
|
||||||
|
|
||||||
.errorMessage {
|
|
||||||
background-color: rgba(239, 68, 68, 0.1);
|
|
||||||
color: #dc2626;
|
|
||||||
border: 1px solid rgba(239, 68, 68, 0.2);
|
|
||||||
}
|
|
||||||
|
|
||||||
.form {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
gap: 2rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.section {
|
|
||||||
background: var(--color-bg);
|
|
||||||
border-radius: 20px;
|
|
||||||
border: 1px solid var(--color-secondary);
|
|
||||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
|
|
||||||
padding: 1.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sectionHeader {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 0.75rem;
|
|
||||||
margin-bottom: 1.5rem;
|
|
||||||
padding-bottom: 0.75rem;
|
|
||||||
border-bottom: 2px solid var(--color-secondary);
|
|
||||||
}
|
|
||||||
|
|
||||||
.sectionIcon {
|
|
||||||
font-size: 1.25rem;
|
|
||||||
color: var(--color-secondary);
|
|
||||||
}
|
|
||||||
|
|
||||||
.sectionTitle {
|
|
||||||
font-size: 1.1rem;
|
|
||||||
font-weight: 600;
|
|
||||||
color: var(--color-text);
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.formRow {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: 1fr 1fr;
|
|
||||||
gap: 1.5rem;
|
|
||||||
margin-bottom: 1.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.formRow:last-child {
|
|
||||||
margin-bottom: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.formField {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
|
|
||||||
.inputContainer {
|
|
||||||
position: relative;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.formInput,
|
|
||||||
.formSelect {
|
|
||||||
width: 100%;
|
|
||||||
padding: 1rem 0.75rem 0.5rem 0.75rem;
|
|
||||||
border: 2px solid var(--color-border);
|
|
||||||
border-radius: 8px;
|
|
||||||
font-size: 1rem;
|
|
||||||
font-family: var(--font-family);
|
|
||||||
background: var(--color-bg);
|
|
||||||
color: var(--color-text);
|
|
||||||
transition: all 0.2s ease;
|
|
||||||
outline: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.formInput:focus,
|
|
||||||
.formSelect:focus {
|
|
||||||
border-color: var(--color-secondary);
|
|
||||||
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);
|
|
||||||
}
|
|
||||||
|
|
||||||
.formInput:invalid:not(:focus) {
|
|
||||||
border-color: #ef4444;
|
|
||||||
}
|
|
||||||
|
|
||||||
.formSelect {
|
|
||||||
appearance: none;
|
|
||||||
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%236b7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='m6 8 4 4 4-4'/%3e%3c/svg%3e");
|
|
||||||
background-position: right 0.5rem center;
|
|
||||||
background-repeat: no-repeat;
|
|
||||||
background-size: 1.5em 1.5em;
|
|
||||||
padding-right: 2.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.floatingLabel {
|
|
||||||
position: absolute;
|
|
||||||
left: 0.75rem;
|
|
||||||
top: 50%;
|
|
||||||
transform: translateY(-50%);
|
|
||||||
background: var(--color-bg);
|
|
||||||
padding: 0 0.25rem;
|
|
||||||
color: var(--color-text-secondary);
|
|
||||||
font-size: 1rem;
|
|
||||||
font-family: var(--font-family);
|
|
||||||
pointer-events: none;
|
|
||||||
transition: all 0.2s ease;
|
|
||||||
z-index: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.floatingLabelActive {
|
|
||||||
top: 0.25rem;
|
|
||||||
transform: translateY(0);
|
|
||||||
font-size: 0.75rem;
|
|
||||||
color: var(--color-secondary);
|
|
||||||
font-weight: 500;
|
|
||||||
}
|
|
||||||
|
|
||||||
.actions {
|
|
||||||
display: flex;
|
|
||||||
gap: 1rem;
|
|
||||||
justify-content: flex-end;
|
|
||||||
align-items: center;
|
|
||||||
padding-top: 1rem;
|
|
||||||
border-top: 1px solid var(--color-border);
|
|
||||||
}
|
|
||||||
|
|
||||||
.resetIcon {
|
|
||||||
margin-right: 0.5rem;
|
|
||||||
font-size: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Responsive Design */
|
|
||||||
@media (max-width: 768px) {
|
|
||||||
.formRow {
|
|
||||||
grid-template-columns: 1fr;
|
|
||||||
gap: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.actions {
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: stretch;
|
|
||||||
}
|
|
||||||
|
|
||||||
.actions button {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: 640px) {
|
|
||||||
.section {
|
|
||||||
padding: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sectionHeader {
|
|
||||||
margin-bottom: 1rem;
|
|
||||||
padding-bottom: 0.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.formRow {
|
|
||||||
gap: 0.75rem;
|
|
||||||
margin-bottom: 1rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,482 +0,0 @@
|
||||||
import { useState, useEffect } from 'react';
|
|
||||||
import { IoIosBusiness, IoIosContact, IoIosTime, IoIosRefresh } from 'react-icons/io';
|
|
||||||
import sharedStyles from '../../core/PageManager/pages.module.css';
|
|
||||||
import styles from './SpeechSettings.module.css';
|
|
||||||
import { useLanguage } from '../../providers/language/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;
|
|
||||||
|
|
@ -1,384 +0,0 @@
|
||||||
.container {
|
|
||||||
max-width: 100%;
|
|
||||||
margin: 0;
|
|
||||||
height: calc(100vh - 120px);
|
|
||||||
overflow-y: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.header {
|
|
||||||
margin-bottom: 1.5rem;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
.backButton {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 0.5rem;
|
|
||||||
background: none;
|
|
||||||
border: none;
|
|
||||||
color: var(--color-text);
|
|
||||||
cursor: pointer;
|
|
||||||
font-size: 1rem;
|
|
||||||
padding: 0.5rem 0;
|
|
||||||
transition: color 0.2s ease;
|
|
||||||
margin-bottom: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.backButton:hover {
|
|
||||||
color: var(--primary-color, #007bff);
|
|
||||||
}
|
|
||||||
|
|
||||||
.backIcon {
|
|
||||||
font-size: 1.2rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.title {
|
|
||||||
font-size: 2rem;
|
|
||||||
font-weight: bold;
|
|
||||||
margin: 0 0 0.5rem 0;
|
|
||||||
color: var(--color-text);
|
|
||||||
}
|
|
||||||
|
|
||||||
.subtitle {
|
|
||||||
color: var(--color-text);
|
|
||||||
margin: 0;
|
|
||||||
line-height: 1.5;
|
|
||||||
}
|
|
||||||
|
|
||||||
.form {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
gap: 1.25rem;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.section {
|
|
||||||
background: var(--color-bg);
|
|
||||||
border: 1px solid var(--color-secondary);
|
|
||||||
border-radius: 25px;
|
|
||||||
padding: 1.25rem;
|
|
||||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
|
|
||||||
}
|
|
||||||
|
|
||||||
.sectionTitle {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 0.75rem;
|
|
||||||
font-size: 1.2rem;
|
|
||||||
font-weight: bold;
|
|
||||||
color: var(--color-secondary);
|
|
||||||
margin: 0 0 1rem 0;
|
|
||||||
padding-bottom: 0.5rem;
|
|
||||||
border-bottom: 2px solid var(--color-secondary);
|
|
||||||
}
|
|
||||||
|
|
||||||
.sectionIcon {
|
|
||||||
font-size: 1.3rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.formGrid {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: repeat(2, 1fr);
|
|
||||||
gap: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.inputGroupFull {
|
|
||||||
grid-column: 1 / -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.inputGroup {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
gap: 0.5rem;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.label {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 0.5rem;
|
|
||||||
font-weight: 500;
|
|
||||||
color: var(--color-text);
|
|
||||||
font-size: 14px;
|
|
||||||
margin-bottom: 6px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.labelIcon {
|
|
||||||
color: var(--color-primary);
|
|
||||||
font-size: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Floating label container */
|
|
||||||
.floatingLabelInput {
|
|
||||||
position: relative;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.input {
|
|
||||||
width: 100%;
|
|
||||||
padding: 12px 12px 8px 12px;
|
|
||||||
border: 1px solid var(--color-primary);
|
|
||||||
border-radius: 25px;
|
|
||||||
font-size: 14px;
|
|
||||||
transition: all 0.2s ease;
|
|
||||||
background-color: var(--color-bg);
|
|
||||||
box-sizing: border-box;
|
|
||||||
color: var(--color-text);
|
|
||||||
}
|
|
||||||
|
|
||||||
.input:focus {
|
|
||||||
outline: none;
|
|
||||||
border-color: var(--color-secondary);
|
|
||||||
}
|
|
||||||
|
|
||||||
.inputError {
|
|
||||||
border-color: #ef4444;
|
|
||||||
box-shadow: 0 0 0 3px rgba(239, 68, 68, 0.1);
|
|
||||||
}
|
|
||||||
|
|
||||||
.inputError:focus {
|
|
||||||
border-color: #ef4444;
|
|
||||||
box-shadow: 0 0 0 3px rgba(239, 68, 68, 0.1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Select styling to match input fields */
|
|
||||||
select.input {
|
|
||||||
appearance: none;
|
|
||||||
background-image: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23666' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3e%3cpolyline points='6,9 12,15 18,9'%3e%3c/polyline%3e%3c/svg%3e");
|
|
||||||
background-repeat: no-repeat;
|
|
||||||
background-position: right 12px center;
|
|
||||||
background-size: 16px;
|
|
||||||
padding-right: 40px;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
select.input:focus {
|
|
||||||
outline: none;
|
|
||||||
border-color: var(--color-secondary);
|
|
||||||
}
|
|
||||||
|
|
||||||
select.input:hover {
|
|
||||||
border-color: var(--color-secondary);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Floating label styles */
|
|
||||||
.floatingLabel {
|
|
||||||
position: absolute;
|
|
||||||
left: 12px;
|
|
||||||
top: 50%;
|
|
||||||
transform: translateY(-50%);
|
|
||||||
color: var(--color-primary);
|
|
||||||
opacity: 0.7;
|
|
||||||
font-size: 14px;
|
|
||||||
transition: all 0.2s ease;
|
|
||||||
pointer-events: none;
|
|
||||||
z-index: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.focusedLabel {
|
|
||||||
position: absolute;
|
|
||||||
left: 12px;
|
|
||||||
top: -8px;
|
|
||||||
transform: translateY(0);
|
|
||||||
color: var(--color-primary);
|
|
||||||
opacity: 1;
|
|
||||||
font-size: 12px;
|
|
||||||
font-weight: 500;
|
|
||||||
background-color: var(--color-bg);
|
|
||||||
padding: 0 4px;
|
|
||||||
transition: all 0.2s ease;
|
|
||||||
pointer-events: none;
|
|
||||||
z-index: 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
.activeFocusedLabel {
|
|
||||||
position: absolute;
|
|
||||||
left: 12px;
|
|
||||||
top: -8px;
|
|
||||||
transform: translateY(0);
|
|
||||||
color: var(--color-secondary);
|
|
||||||
opacity: 1;
|
|
||||||
font-size: 12px;
|
|
||||||
font-weight: 500;
|
|
||||||
background-color: var(--color-bg);
|
|
||||||
padding: 0 4px;
|
|
||||||
transition: all 0.2s ease;
|
|
||||||
pointer-events: none;
|
|
||||||
z-index: 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
.textarea {
|
|
||||||
width: 100%;
|
|
||||||
padding: 12px 12px 8px 12px;
|
|
||||||
border: 1px solid var(--color-primary);
|
|
||||||
border-radius: 25px;
|
|
||||||
font-size: 14px;
|
|
||||||
transition: all 0.2s ease;
|
|
||||||
background-color: var(--color-bg);
|
|
||||||
box-sizing: border-box;
|
|
||||||
color: var(--color-text);
|
|
||||||
font-family: inherit;
|
|
||||||
line-height: 1.5;
|
|
||||||
overflow-y: auto;
|
|
||||||
resize: vertical;
|
|
||||||
min-height: 4em;
|
|
||||||
max-height: 8em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.textarea:focus {
|
|
||||||
outline: none;
|
|
||||||
border-color: var(--color-secondary);
|
|
||||||
}
|
|
||||||
|
|
||||||
.textarea.inputError {
|
|
||||||
border-color: #ef4444;
|
|
||||||
box-shadow: 0 0 0 3px rgba(239, 68, 68, 0.1);
|
|
||||||
}
|
|
||||||
|
|
||||||
.errorText {
|
|
||||||
color: #ef4444;
|
|
||||||
font-size: 12px;
|
|
||||||
margin-top: 4px;
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
.contactsSection {
|
|
||||||
text-align: center;
|
|
||||||
padding: 1rem 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.contactsDescription {
|
|
||||||
color: var(--color-text);
|
|
||||||
margin-bottom: 1.5rem;
|
|
||||||
line-height: 1.5;
|
|
||||||
}
|
|
||||||
|
|
||||||
.contactsActions {
|
|
||||||
display: flex;
|
|
||||||
gap: 1rem;
|
|
||||||
justify-content: center;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
.skipButton {
|
|
||||||
padding: 8px 16px;
|
|
||||||
border: 1px solid var(--color-primary);
|
|
||||||
background-color: var(--color-bg);
|
|
||||||
color: var(--color-text);
|
|
||||||
border-radius: 25px;
|
|
||||||
font-size: 14px;
|
|
||||||
font-weight: 500;
|
|
||||||
cursor: pointer;
|
|
||||||
transition: all 0.2s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.skipButton:hover {
|
|
||||||
background-color: var(--color-primary-hover);
|
|
||||||
border-color: var(--color-primary);
|
|
||||||
color: #181818;
|
|
||||||
}
|
|
||||||
|
|
||||||
.setupButton {
|
|
||||||
padding: 8px 16px;
|
|
||||||
border: none;
|
|
||||||
background-color: var(--color-secondary);
|
|
||||||
color: var(--color-bg);
|
|
||||||
border-radius: 25px;
|
|
||||||
font-size: 14px;
|
|
||||||
font-weight: 500;
|
|
||||||
cursor: pointer;
|
|
||||||
transition: all 0.2s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.setupButton:hover {
|
|
||||||
background-color: var(--color-secondary-hover);
|
|
||||||
}
|
|
||||||
|
|
||||||
.actions {
|
|
||||||
display: flex;
|
|
||||||
justify-content: flex-end;
|
|
||||||
gap: 12px;
|
|
||||||
margin-top: 24px;
|
|
||||||
padding-top: 16px;
|
|
||||||
border-top: 1px solid var(--color-primary);
|
|
||||||
}
|
|
||||||
|
|
||||||
.cancelButton {
|
|
||||||
padding: 8px 16px;
|
|
||||||
border: 1px solid var(--color-primary);
|
|
||||||
background-color: var(--color-bg);
|
|
||||||
color: var(--color-text);
|
|
||||||
border-radius: 25px;
|
|
||||||
font-size: 14px;
|
|
||||||
font-weight: 500;
|
|
||||||
cursor: pointer;
|
|
||||||
transition: all 0.2s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.cancelButton:hover {
|
|
||||||
background-color: var(--color-primary-hover);
|
|
||||||
border-color: var(--color-primary);
|
|
||||||
color: #181818;
|
|
||||||
}
|
|
||||||
|
|
||||||
.submitButton {
|
|
||||||
padding: 8px 16px;
|
|
||||||
border: none;
|
|
||||||
background-color: var(--color-secondary);
|
|
||||||
color: var(--color-bg);
|
|
||||||
border-radius: 25px;
|
|
||||||
font-size: 14px;
|
|
||||||
font-weight: 500;
|
|
||||||
cursor: pointer;
|
|
||||||
transition: all 0.2s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.submitButton:hover {
|
|
||||||
background-color: var(--color-secondary-hover);
|
|
||||||
}
|
|
||||||
|
|
||||||
.submitButton:disabled {
|
|
||||||
background-color: #9ca3af;
|
|
||||||
cursor: not-allowed;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: 640px) {
|
|
||||||
.container {
|
|
||||||
padding: 1rem;
|
|
||||||
height: calc(100vh - 100px);
|
|
||||||
}
|
|
||||||
|
|
||||||
.formGrid {
|
|
||||||
grid-template-columns: 1fr;
|
|
||||||
gap: 0.75rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.section {
|
|
||||||
padding: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sectionTitle {
|
|
||||||
font-size: 1.1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.contactsActions {
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.skipButton,
|
|
||||||
.setupButton {
|
|
||||||
width: 100%;
|
|
||||||
max-width: 200px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.actions {
|
|
||||||
flex-direction: column-reverse;
|
|
||||||
}
|
|
||||||
|
|
||||||
.cancelButton,
|
|
||||||
.submitButton {
|
|
||||||
width: 100%;
|
|
||||||
padding: 12px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,342 +0,0 @@
|
||||||
import { useState } from 'react';
|
|
||||||
import { IoIosArrowBack, IoIosBusiness, IoIosPeople } from 'react-icons/io';
|
|
||||||
import sharedStyles from '../../core/PageManager/pages.module.css';
|
|
||||||
import styles from './SpeechSignUp.module.css';
|
|
||||||
import { useLanguage } from '../../providers/language/LanguageContext';
|
|
||||||
|
|
||||||
interface SpeechSignUpProps {
|
|
||||||
onBack: () => void;
|
|
||||||
onSubmit: (data: MandateData) => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
function SpeechSignUp({ onBack, onSubmit }: SpeechSignUpProps) {
|
|
||||||
const { t } = useLanguage();
|
|
||||||
|
|
||||||
const [formData, setFormData] = useState<MandateData>({
|
|
||||||
id: crypto.randomUUID(),
|
|
||||||
mandate_general: {
|
|
||||||
company_name: '',
|
|
||||||
industry: '',
|
|
||||||
contact_info: {
|
|
||||||
email: '',
|
|
||||||
phone: '',
|
|
||||||
street: '',
|
|
||||||
postal_code: '',
|
|
||||||
city: '',
|
|
||||||
country: ''
|
|
||||||
},
|
|
||||||
business_hours: '9:00-17:00',
|
|
||||||
timezone: 'Europe/Zurich'
|
|
||||||
},
|
|
||||||
setup_contacts: false
|
|
||||||
});
|
|
||||||
|
|
||||||
const [errors, setErrors] = useState<Record<string, string>>({});
|
|
||||||
const [focusedFields, setFocusedFields] = useState<Set<string>>(new Set());
|
|
||||||
|
|
||||||
const handleInputChange = (field: string, value: string) => {
|
|
||||||
if (field.startsWith('contact_info.')) {
|
|
||||||
const contactField = field.split('.')[1] as keyof typeof formData.mandate_general.contact_info;
|
|
||||||
setFormData(prev => ({
|
|
||||||
...prev,
|
|
||||||
mandate_general: {
|
|
||||||
...prev.mandate_general,
|
|
||||||
contact_info: {
|
|
||||||
...prev.mandate_general.contact_info,
|
|
||||||
[contactField]: value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
} else if (field.startsWith('mandate_general.')) {
|
|
||||||
const generalField = field.split('.')[1] as keyof typeof formData.mandate_general;
|
|
||||||
setFormData(prev => ({
|
|
||||||
...prev,
|
|
||||||
mandate_general: {
|
|
||||||
...prev.mandate_general,
|
|
||||||
[generalField]: value
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
} else {
|
|
||||||
setFormData(prev => ({ ...prev, [field]: value }));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clear error when user starts typing
|
|
||||||
if (errors[field]) {
|
|
||||||
setErrors(prev => ({ ...prev, [field]: '' }));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
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 validateForm = (): boolean => {
|
|
||||||
const newErrors: Record<string, string> = {};
|
|
||||||
|
|
||||||
if (!formData.mandate_general.company_name.trim()) newErrors['mandate_general.company_name'] = t('speech.signup.company_required');
|
|
||||||
if (!formData.mandate_general.industry.trim()) newErrors['mandate_general.industry'] = t('speech.signup.industry_required');
|
|
||||||
if (!formData.mandate_general.contact_info.email.trim()) {
|
|
||||||
newErrors['contact_info.email'] = t('speech.signup.email_required');
|
|
||||||
} else if (!/\S+@\S+\.\S+/.test(formData.mandate_general.contact_info.email)) {
|
|
||||||
newErrors['contact_info.email'] = t('speech.signup.email_invalid');
|
|
||||||
}
|
|
||||||
if (!formData.mandate_general.contact_info.phone.trim()) newErrors['contact_info.phone'] = t('speech.signup.phone_required');
|
|
||||||
if (!formData.mandate_general.contact_info.street.trim()) newErrors['contact_info.street'] = t('speech.signup.street_required');
|
|
||||||
if (!formData.mandate_general.contact_info.postal_code.trim()) newErrors['contact_info.postal_code'] = t('speech.signup.postal_code_required');
|
|
||||||
if (!formData.mandate_general.contact_info.city.trim()) newErrors['contact_info.city'] = t('speech.signup.city_required');
|
|
||||||
if (!formData.mandate_general.contact_info.country.trim()) newErrors['contact_info.country'] = t('speech.signup.country_required');
|
|
||||||
|
|
||||||
setErrors(newErrors);
|
|
||||||
return Object.keys(newErrors).length === 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleSubmit = (e: React.FormEvent) => {
|
|
||||||
e.preventDefault();
|
|
||||||
if (validateForm()) {
|
|
||||||
// Save to localStorage for session persistence
|
|
||||||
try {
|
|
||||||
localStorage.setItem('speechSignUpData', JSON.stringify(formData));
|
|
||||||
localStorage.setItem('speechSignUpTimestamp', Date.now().toString());
|
|
||||||
console.log('Sign-up data saved to localStorage:', formData);
|
|
||||||
|
|
||||||
// Dispatch custom event to refresh sidebar
|
|
||||||
window.dispatchEvent(new CustomEvent('speechSignUpChanged'));
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Failed to save to localStorage:', error);
|
|
||||||
}
|
|
||||||
|
|
||||||
onSubmit(formData);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const renderFloatingInput = (
|
|
||||||
field: string,
|
|
||||||
value: string,
|
|
||||||
placeholder: string,
|
|
||||||
type: string = 'text',
|
|
||||||
icon?: React.ReactNode
|
|
||||||
) => {
|
|
||||||
const isFocused = focusedFields.has(field);
|
|
||||||
const hasValue = value.trim() !== '';
|
|
||||||
const hasError = errors[field];
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className={styles.floatingLabelInput}>
|
|
||||||
<input
|
|
||||||
type={type}
|
|
||||||
value={value}
|
|
||||||
onChange={(e) => handleInputChange(field, e.target.value)}
|
|
||||||
onFocus={() => handleFocus(field)}
|
|
||||||
onBlur={() => handleBlur(field)}
|
|
||||||
className={`${styles.input} ${hasError ? styles.inputError : ''}`}
|
|
||||||
placeholder=""
|
|
||||||
/>
|
|
||||||
<label className={
|
|
||||||
isFocused || hasValue
|
|
||||||
? hasError
|
|
||||||
? styles.focusedLabel
|
|
||||||
: styles.activeFocusedLabel
|
|
||||||
: styles.floatingLabel
|
|
||||||
}>
|
|
||||||
{icon}
|
|
||||||
{placeholder}
|
|
||||||
</label>
|
|
||||||
{hasError && <span className={styles.errorText}>{hasError}</span>}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className={styles.container}>
|
|
||||||
<div className={styles.header}>
|
|
||||||
<button
|
|
||||||
className={styles.backButton}
|
|
||||||
onClick={onBack}
|
|
||||||
type="button"
|
|
||||||
>
|
|
||||||
<IoIosArrowBack className={styles.backIcon} />
|
|
||||||
{t('speech.signup.back')}
|
|
||||||
</button>
|
|
||||||
<h1 className={styles.title}>{t('speech.signup.title')}</h1>
|
|
||||||
<p className={styles.subtitle}>
|
|
||||||
{t('speech.signup.subtitle')}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<form onSubmit={handleSubmit} className={styles.form}>
|
|
||||||
<div className={styles.section}>
|
|
||||||
<h2 className={styles.sectionTitle}>
|
|
||||||
<IoIosBusiness className={styles.sectionIcon} />
|
|
||||||
{t('speech.signup.company_info')}
|
|
||||||
</h2>
|
|
||||||
|
|
||||||
<div className={styles.formGrid}>
|
|
||||||
{renderFloatingInput(
|
|
||||||
'mandate_general.company_name',
|
|
||||||
formData.mandate_general.company_name,
|
|
||||||
`${t('speech.signup.company_name')} *`
|
|
||||||
)}
|
|
||||||
|
|
||||||
{renderFloatingInput(
|
|
||||||
'mandate_general.industry',
|
|
||||||
formData.mandate_general.industry,
|
|
||||||
`${t('speech.signup.industry')} *`
|
|
||||||
)}
|
|
||||||
|
|
||||||
{renderFloatingInput(
|
|
||||||
'mandate_general.business_hours',
|
|
||||||
formData.mandate_general.business_hours,
|
|
||||||
`${t('speech.signup.business_hours')}`,
|
|
||||||
'text',
|
|
||||||
|
|
||||||
)}
|
|
||||||
|
|
||||||
<div className={styles.floatingLabelInput}>
|
|
||||||
<select
|
|
||||||
value={formData.mandate_general.timezone}
|
|
||||||
onChange={(e) => handleInputChange('mandate_general.timezone', e.target.value)}
|
|
||||||
onFocus={() => handleFocus('mandate_general.timezone')}
|
|
||||||
onBlur={() => handleBlur('mandate_general.timezone')}
|
|
||||||
className={styles.input}
|
|
||||||
>
|
|
||||||
<option value="Europe/Zurich">Europe/Zurich</option>
|
|
||||||
<option value="Europe/Berlin">Europe/Berlin</option>
|
|
||||||
<option value="Europe/Paris">Europe/Paris</option>
|
|
||||||
<option value="Europe/London">Europe/London</option>
|
|
||||||
<option value="America/New_York">America/New_York</option>
|
|
||||||
</select>
|
|
||||||
<label className={
|
|
||||||
focusedFields.has('mandate_general.timezone') || formData.mandate_general.timezone.trim() !== ''
|
|
||||||
? styles.activeFocusedLabel
|
|
||||||
: styles.floatingLabel
|
|
||||||
}>
|
|
||||||
{t('speech.signup.timezone')}
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className={styles.section}>
|
|
||||||
<h2 className={styles.sectionTitle}>
|
|
||||||
|
|
||||||
{t('speech.signup.contact_info')}
|
|
||||||
</h2>
|
|
||||||
|
|
||||||
<div className={styles.formGrid}>
|
|
||||||
{renderFloatingInput(
|
|
||||||
'contact_info.email',
|
|
||||||
formData.mandate_general.contact_info.email,
|
|
||||||
`${t('speech.signup.email')} *`,
|
|
||||||
'email'
|
|
||||||
)}
|
|
||||||
|
|
||||||
{renderFloatingInput(
|
|
||||||
'contact_info.phone',
|
|
||||||
formData.mandate_general.contact_info.phone,
|
|
||||||
`${t('speech.signup.phone')} *`,
|
|
||||||
'tel',
|
|
||||||
|
|
||||||
)}
|
|
||||||
|
|
||||||
{renderFloatingInput(
|
|
||||||
'contact_info.street',
|
|
||||||
formData.mandate_general.contact_info.street,
|
|
||||||
`${t('speech.signup.street')} *`
|
|
||||||
)}
|
|
||||||
|
|
||||||
{renderFloatingInput(
|
|
||||||
'contact_info.postal_code',
|
|
||||||
formData.mandate_general.contact_info.postal_code,
|
|
||||||
`${t('speech.signup.postal_code')} *`
|
|
||||||
)}
|
|
||||||
|
|
||||||
{renderFloatingInput(
|
|
||||||
'contact_info.city',
|
|
||||||
formData.mandate_general.contact_info.city,
|
|
||||||
`${t('speech.signup.city')} *`
|
|
||||||
)}
|
|
||||||
|
|
||||||
{renderFloatingInput(
|
|
||||||
'contact_info.country',
|
|
||||||
formData.mandate_general.contact_info.country,
|
|
||||||
`${t('speech.signup.country')} *`
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className={styles.section}>
|
|
||||||
<h2 className={styles.sectionTitle}>
|
|
||||||
<IoIosPeople className={styles.sectionIcon} />
|
|
||||||
{t('speech.signup.contacts_setup')}
|
|
||||||
</h2>
|
|
||||||
<div className={styles.contactsSection}>
|
|
||||||
<p className={styles.contactsDescription}>
|
|
||||||
{t('speech.signup.contacts_description')}
|
|
||||||
</p>
|
|
||||||
<div className={styles.contactsActions}>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
className={`${sharedStyles.secondaryButton} ${styles.skipButton}`}
|
|
||||||
onClick={() => handleInputChange('setup_contacts', 'false')}
|
|
||||||
>
|
|
||||||
{t('speech.signup.skip_for_now')}
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
className={`${sharedStyles.primaryButton} ${styles.setupButton}`}
|
|
||||||
onClick={() => handleInputChange('setup_contacts', 'true')}
|
|
||||||
>
|
|
||||||
{t('speech.signup.setup_contacts')}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className={styles.actions}>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
className={`${sharedStyles.secondaryButton} ${styles.cancelButton}`}
|
|
||||||
onClick={onBack}
|
|
||||||
>
|
|
||||||
{t('speech.signup.cancel')}
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
type="submit"
|
|
||||||
className={`${sharedStyles.primaryButton} ${styles.submitButton}`}
|
|
||||||
>
|
|
||||||
{t('speech.signup.submit')}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default SpeechSignUp;
|
|
||||||
|
|
@ -1,4 +0,0 @@
|
||||||
export { default as SpeechInfo } from './SpeechInfo';
|
|
||||||
export { default as SpeechSignUp } from './SpeechSignUp';
|
|
||||||
export { default as SpeechConfirmation } from './SpeechConfirmation';
|
|
||||||
export { default as SpeechSettings } from './SpeechSettings';
|
|
||||||
|
|
@ -1,113 +0,0 @@
|
||||||
import { GenericPageData } from '../../pageInterface';
|
|
||||||
import { FaDownload, FaTrash, FaSearch } from 'react-icons/fa';
|
|
||||||
import { IoIosDocument } from 'react-icons/io';
|
|
||||||
|
|
||||||
export const speechTranscriptsPageData: GenericPageData = {
|
|
||||||
id: '8-1',
|
|
||||||
path: 'speech/transcripts',
|
|
||||||
name: 'Transkriptverwaltung',
|
|
||||||
description: 'Manage and organize speech transcripts',
|
|
||||||
|
|
||||||
// Parent page
|
|
||||||
parentPath: 'speech',
|
|
||||||
|
|
||||||
// Visual
|
|
||||||
icon: IoIosDocument,
|
|
||||||
title: 'Transkriptverwaltung',
|
|
||||||
subtitle: 'Manage your speech transcripts and recordings',
|
|
||||||
|
|
||||||
// Header buttons
|
|
||||||
headerButtons: [
|
|
||||||
{
|
|
||||||
id: 'search',
|
|
||||||
label: 'Search',
|
|
||||||
variant: 'secondary',
|
|
||||||
size: 'md',
|
|
||||||
icon: FaSearch,
|
|
||||||
onClick: () => {
|
|
||||||
console.log('Opening search...');
|
|
||||||
// Add search logic here
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'export-all',
|
|
||||||
label: 'Export All',
|
|
||||||
variant: 'primary',
|
|
||||||
size: 'md',
|
|
||||||
icon: FaDownload,
|
|
||||||
onClick: () => {
|
|
||||||
console.log('Exporting all transcripts...');
|
|
||||||
// Add export logic here
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'delete-old',
|
|
||||||
label: 'Delete Old',
|
|
||||||
variant: 'danger',
|
|
||||||
size: 'md',
|
|
||||||
icon: FaTrash,
|
|
||||||
onClick: () => {
|
|
||||||
console.log('Deleting old transcripts...');
|
|
||||||
// Add delete logic here
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
|
|
||||||
// Content sections
|
|
||||||
content: [
|
|
||||||
{
|
|
||||||
id: 'intro',
|
|
||||||
type: 'heading',
|
|
||||||
content: 'Transcript Management',
|
|
||||||
level: 2
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'description',
|
|
||||||
type: 'paragraph',
|
|
||||||
content: 'View, organize, and manage all your speech transcripts in one place. Search through your recordings and export them in various formats.'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'features',
|
|
||||||
type: 'heading',
|
|
||||||
content: 'Available Actions',
|
|
||||||
level: 3
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'features-list',
|
|
||||||
type: 'list',
|
|
||||||
content: 'You can:',
|
|
||||||
items: [
|
|
||||||
'Search through all your transcripts',
|
|
||||||
'Filter by date, duration, or content',
|
|
||||||
'Export individual or multiple transcripts',
|
|
||||||
'Edit and correct transcriptions',
|
|
||||||
'Add tags and notes to recordings',
|
|
||||||
'Delete old or unwanted recordings'
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'organization',
|
|
||||||
type: 'heading',
|
|
||||||
content: 'Organization Tips',
|
|
||||||
level: 3
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'organization-text',
|
|
||||||
type: 'paragraph',
|
|
||||||
content: 'Use tags to organize your transcripts by topic or project. You can also add custom notes to help you find specific recordings later.'
|
|
||||||
}
|
|
||||||
],
|
|
||||||
|
|
||||||
// Page behavior
|
|
||||||
persistent: false,
|
|
||||||
preload: false,
|
|
||||||
moduleEnabled: true,
|
|
||||||
|
|
||||||
// Sidebar - will be shown as subpage under Speech
|
|
||||||
showInSidebar: false,
|
|
||||||
|
|
||||||
// Lifecycle hooks
|
|
||||||
onActivate: async () => {
|
|
||||||
if (import.meta.env.DEV) console.log('Speech Transcripts activated');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
@ -1,125 +0,0 @@
|
||||||
import { GenericPageData } from '../../pageInterface';
|
|
||||||
import { FaRegFileAlt, FaMicrophone, FaCog, FaHistory } from 'react-icons/fa';
|
|
||||||
|
|
||||||
export const speechPageData: GenericPageData = {
|
|
||||||
id: 'start-speech',
|
|
||||||
path: 'start/speech',
|
|
||||||
name: 'Speech',
|
|
||||||
description: 'Speech recognition and transcription tools',
|
|
||||||
|
|
||||||
// Parent page
|
|
||||||
parentPath: 'start',
|
|
||||||
showInSidebar: false,
|
|
||||||
|
|
||||||
// Visual
|
|
||||||
icon: FaRegFileAlt,
|
|
||||||
title: 'Speech Recognition',
|
|
||||||
subtitle: 'Convert speech to text with AI-powered transcription',
|
|
||||||
|
|
||||||
// Header buttons
|
|
||||||
headerButtons: [
|
|
||||||
{
|
|
||||||
id: 'start-recording',
|
|
||||||
label: 'Start Recording',
|
|
||||||
variant: 'primary',
|
|
||||||
size: 'lg',
|
|
||||||
icon: FaMicrophone,
|
|
||||||
onClick: () => {
|
|
||||||
console.log('Starting speech recording...');
|
|
||||||
// Add recording logic here
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'settings',
|
|
||||||
label: 'Settings',
|
|
||||||
variant: 'secondary',
|
|
||||||
size: 'md',
|
|
||||||
icon: FaCog,
|
|
||||||
onClick: () => {
|
|
||||||
console.log('Opening speech settings...');
|
|
||||||
// Navigate to settings
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'view-transcripts',
|
|
||||||
label: 'View Transcripts',
|
|
||||||
variant: 'secondary',
|
|
||||||
size: 'md',
|
|
||||||
icon: FaHistory,
|
|
||||||
onClick: () => {
|
|
||||||
console.log('Opening transcript history...');
|
|
||||||
// Navigate to transcripts
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
|
|
||||||
// Content sections
|
|
||||||
content: [
|
|
||||||
{
|
|
||||||
id: 'intro',
|
|
||||||
type: 'heading',
|
|
||||||
content: 'Speech Recognition',
|
|
||||||
level: 2
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'description',
|
|
||||||
type: 'paragraph',
|
|
||||||
content: 'Use advanced AI-powered speech recognition to convert your spoken words into text. Perfect for dictation, meeting notes, and accessibility.'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'features',
|
|
||||||
type: 'heading',
|
|
||||||
content: 'Features',
|
|
||||||
level: 3
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'features-list',
|
|
||||||
type: 'list',
|
|
||||||
content: 'Available features:',
|
|
||||||
items: [
|
|
||||||
'Real-time speech-to-text conversion',
|
|
||||||
'Multiple language support',
|
|
||||||
'Custom vocabulary and commands',
|
|
||||||
'Automatic punctuation and formatting',
|
|
||||||
'Export to various formats (TXT, DOCX, PDF)',
|
|
||||||
'Cloud and offline processing options'
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'getting-started',
|
|
||||||
type: 'heading',
|
|
||||||
content: 'Getting Started',
|
|
||||||
level: 3
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'getting-started-text',
|
|
||||||
type: 'paragraph',
|
|
||||||
content: 'Click the "Start Recording" button above to begin. Make sure your microphone is connected and you have granted permission for the browser to access it.'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'privacy-note',
|
|
||||||
type: 'heading',
|
|
||||||
content: 'Privacy & Security',
|
|
||||||
level: 3
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'privacy-text',
|
|
||||||
type: 'paragraph',
|
|
||||||
content: 'Your speech data is processed securely and can be processed either locally on your device or in our secure cloud environment. You can choose your preferred processing method in the settings.'
|
|
||||||
}
|
|
||||||
],
|
|
||||||
|
|
||||||
// Subpage support
|
|
||||||
hasSubpages: true,
|
|
||||||
|
|
||||||
// Page behavior
|
|
||||||
persistent: false,
|
|
||||||
preload: true,
|
|
||||||
moduleEnabled: true,
|
|
||||||
hide: true, // Completely hide this page - it will not be rendered
|
|
||||||
|
|
||||||
// Lifecycle hooks
|
|
||||||
onActivate: async () => {
|
|
||||||
if (import.meta.env.DEV) console.log('Speech activated');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
Loading…
Reference in a new issue