diff --git a/src/components/Speech/SpeechConfirmation.module.css b/src/components/Speech/SpeechConfirmation.module.css deleted file mode 100644 index fbdcd84..0000000 --- a/src/components/Speech/SpeechConfirmation.module.css +++ /dev/null @@ -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; - } -} diff --git a/src/components/Speech/SpeechConfirmation.tsx b/src/components/Speech/SpeechConfirmation.tsx deleted file mode 100644 index b245fdd..0000000 --- a/src/components/Speech/SpeechConfirmation.tsx +++ /dev/null @@ -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 ( -
-
-
- -
- -

{t('speech.confirmation.title')}

- -

- {t('speech.confirmation.message')} -

- - {submittedData && ( -
-

{t('speech.confirmation.submitted_data')}

-
-
- {t('speech.confirmation.company')}: - {submittedData.mandate_general.company_name} -
-
- {t('speech.confirmation.industry')}: - {submittedData.mandate_general.industry} -
-
- {t('speech.confirmation.email')}: - {submittedData.mandate_general.contact_info.email} -
-
- {t('speech.confirmation.phone')}: - {submittedData.mandate_general.contact_info.phone} -
-
- {t('speech.confirmation.address')}: - - {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} - -
-
- {t('speech.confirmation.timezone')}: - {submittedData.mandate_general.timezone} -
-
-
- )} - -
-

{t('speech.confirmation.next_steps')}

- -
-
- -
-
-

{t('speech.confirmation.email_confirmation')}

-

{t('speech.confirmation.email_confirmation_desc')}

-
-
- -
-
- -
-
-

{t('speech.confirmation.review_process')}

-

{t('speech.confirmation.review_process_desc')}

-
-
- -
-
- -
-
-

{t('speech.confirmation.setup_call')}

-

{t('speech.confirmation.setup_call_desc')}

-
-
-
- -
-

{t('speech.confirmation.questions')}

-

- {t('speech.confirmation.questions_desc')} -

-
-
- - support@spitch.ai -
-
- - +1 (555) 123-4567 -
-
-
-
- -
- - {onReset && ( - - )} -
- -
- - -
-
- ); -} - -export default SpeechConfirmation; diff --git a/src/components/Speech/SpeechInfo.module.css b/src/components/Speech/SpeechInfo.module.css deleted file mode 100644 index e710a5e..0000000 --- a/src/components/Speech/SpeechInfo.module.css +++ /dev/null @@ -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; - } - -} diff --git a/src/components/Speech/SpeechInfo.tsx b/src/components/Speech/SpeechInfo.tsx deleted file mode 100644 index b690dfe..0000000 --- a/src/components/Speech/SpeechInfo.tsx +++ /dev/null @@ -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 ( -
-
-
- {features.map((feature) => ( -
-
- {feature.key.toUpperCase()} -
-

{feature.title}

-

{feature.description}

-
- ))} -
- -
-

{t('speech.info.about')}

-

- {t('speech.info.about_intro')} -

- -
-
-

🎯 {t('speech.info.workflow_title')}

-

{t('speech.info.workflow_description')}

-
- -
-

🤖 {t('speech.info.ai_title')}

-

{t('speech.info.ai_description')}

-
- -
-

🔄 {t('speech.info.sync_title')}

-

{t('speech.info.sync_description')}

-
- -
-

💰 {t('speech.info.cost_title')}

-

{t('speech.info.cost_description')}

-
-
- -
- - - {t('speech.info.about_link')} - -
-
-
-
- ); -} - -export default SpeechInfo; diff --git a/src/components/Speech/SpeechSettings.module.css b/src/components/Speech/SpeechSettings.module.css deleted file mode 100644 index 5b07f15..0000000 --- a/src/components/Speech/SpeechSettings.module.css +++ /dev/null @@ -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; - } -} diff --git a/src/components/Speech/SpeechSettings.tsx b/src/components/Speech/SpeechSettings.tsx deleted file mode 100644 index 013243b..0000000 --- a/src/components/Speech/SpeechSettings.tsx +++ /dev/null @@ -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(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>(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 ( -
-
- {t('common.loading')} -
-
- ); - } - - if (!formData) { - return ( -
-
-

{t('speech.settings.no_data')}

- -
-
- ); - } - - return ( -
-
-

{t('speech.settings.title')}

-

{t('speech.settings.description')}

-
- - {saveMessage && ( -
- {saveMessage.text} -
- )} - -
- {/* Company Information Section */} -
-
- -

{t('speech.settings.company_info')}

-
- -
-
-
- handleInputChange('mandate_general.company_name', e.target.value)} - onFocus={() => handleFocus('company_name')} - onBlur={() => handleBlur('company_name')} - required - /> - -
-
- -
-
- handleInputChange('mandate_general.industry', e.target.value)} - onFocus={() => handleFocus('industry')} - onBlur={() => handleBlur('industry')} - required - /> - -
-
-
-
- - {/* Contact Information Section */} -
-
- -

{t('speech.settings.contact_info')}

-
- -
-
-
- handleInputChange('mandate_general.contact_info.email', e.target.value)} - onFocus={() => handleFocus('email')} - onBlur={() => handleBlur('email')} - required - /> - -
-
- -
-
- handleInputChange('mandate_general.contact_info.phone', e.target.value)} - onFocus={() => handleFocus('phone')} - onBlur={() => handleBlur('phone')} - required - /> - -
-
-
- -
-
-
- handleInputChange('mandate_general.contact_info.street', e.target.value)} - onFocus={() => handleFocus('street')} - onBlur={() => handleBlur('street')} - required - /> - -
-
- -
-
- handleInputChange('mandate_general.contact_info.postal_code', e.target.value)} - onFocus={() => handleFocus('postal_code')} - onBlur={() => handleBlur('postal_code')} - required - /> - -
-
-
- -
-
-
- handleInputChange('mandate_general.contact_info.city', e.target.value)} - onFocus={() => handleFocus('city')} - onBlur={() => handleBlur('city')} - required - /> - -
-
- -
-
- handleInputChange('mandate_general.contact_info.country', e.target.value)} - onFocus={() => handleFocus('country')} - onBlur={() => handleBlur('country')} - required - /> - -
-
-
-
- - {/* Business Hours Section */} -
-
- -

{t('speech.settings.business_hours')}

-
- -
-
-
- handleInputChange('mandate_general.business_hours', e.target.value)} - onFocus={() => handleFocus('business_hours')} - onBlur={() => handleBlur('business_hours')} - required - /> - -
-
- -
-
- - -
-
-
-
- - {/* Actions */} -
- - - -
-
-
- ); -} - -export default SpeechSettings; diff --git a/src/components/Speech/SpeechSignUp.module.css b/src/components/Speech/SpeechSignUp.module.css deleted file mode 100644 index 62e2216..0000000 --- a/src/components/Speech/SpeechSignUp.module.css +++ /dev/null @@ -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; - } -} diff --git a/src/components/Speech/SpeechSignUp.tsx b/src/components/Speech/SpeechSignUp.tsx deleted file mode 100644 index 0c98f34..0000000 --- a/src/components/Speech/SpeechSignUp.tsx +++ /dev/null @@ -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({ - 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>({}); - const [focusedFields, setFocusedFields] = useState>(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 = {}; - - 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 ( -
- handleInputChange(field, e.target.value)} - onFocus={() => handleFocus(field)} - onBlur={() => handleBlur(field)} - className={`${styles.input} ${hasError ? styles.inputError : ''}`} - placeholder="" - /> - - {hasError && {hasError}} -
- ); - }; - - return ( -
-
- -

{t('speech.signup.title')}

-

- {t('speech.signup.subtitle')} -

-
- -
-
-

- - {t('speech.signup.company_info')} -

- -
- {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', - - )} - -
- - -
-
-
- -
-

- - {t('speech.signup.contact_info')} -

- -
- {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')} *` - )} -
-
- -
-

- - {t('speech.signup.contacts_setup')} -

-
-

- {t('speech.signup.contacts_description')} -

-
- - -
-
-
- -
- - -
-
-
- ); -} - -export default SpeechSignUp; diff --git a/src/components/Speech/index.ts b/src/components/Speech/index.ts deleted file mode 100644 index c9d68ac..0000000 --- a/src/components/Speech/index.ts +++ /dev/null @@ -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'; diff --git a/src/core/PageManager/data/pages/speech-transcripts.ts b/src/core/PageManager/data/pages/speech-transcripts.ts deleted file mode 100644 index f3de874..0000000 --- a/src/core/PageManager/data/pages/speech-transcripts.ts +++ /dev/null @@ -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'); - } -}; diff --git a/src/core/PageManager/data/pages/speech.ts b/src/core/PageManager/data/pages/speech.ts deleted file mode 100644 index 3f619bc..0000000 --- a/src/core/PageManager/data/pages/speech.ts +++ /dev/null @@ -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'); - } -};