fix: ready for build
This commit is contained in:
parent
9519fed195
commit
8a0e5f88a1
27 changed files with 79 additions and 128 deletions
18
package-lock.json
generated
18
package-lock.json
generated
|
|
@ -30,6 +30,7 @@
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/js": "^9.30.1",
|
"@eslint/js": "^9.30.1",
|
||||||
|
"@types/node": "^24.7.2",
|
||||||
"@types/react": "^19.1.8",
|
"@types/react": "^19.1.8",
|
||||||
"@types/react-dom": "^19.1.6",
|
"@types/react-dom": "^19.1.6",
|
||||||
"@vitejs/plugin-react": "^4.6.0",
|
"@vitejs/plugin-react": "^4.6.0",
|
||||||
|
|
@ -1432,6 +1433,16 @@
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/node": {
|
||||||
|
"version": "24.7.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.7.2.tgz",
|
||||||
|
"integrity": "sha512-/NbVmcGTP+lj5oa4yiYxxeBjRivKQ5Ns1eSZeB99ExsEQ6rX5XYU1Zy/gGxY/ilqtD4Etx9mKyrPxZRetiahhA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"undici-types": "~7.14.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@types/react": {
|
"node_modules/@types/react": {
|
||||||
"version": "19.1.8",
|
"version": "19.1.8",
|
||||||
"resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.8.tgz",
|
"resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.8.tgz",
|
||||||
|
|
@ -5083,6 +5094,13 @@
|
||||||
"typescript": ">=4.8.4 <5.9.0"
|
"typescript": ">=4.8.4 <5.9.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/undici-types": {
|
||||||
|
"version": "7.14.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.14.0.tgz",
|
||||||
|
"integrity": "sha512-QQiYxHuyZ9gQUIrmPo3IA+hUl4KYk8uSA7cHrcKd/l3p1OTpZcM0Tbp9x7FAtXdAYhlasd60ncPpgu6ihG6TOA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/universalify": {
|
"node_modules/universalify": {
|
||||||
"version": "2.0.1",
|
"version": "2.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz",
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,7 @@
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/js": "^9.30.1",
|
"@eslint/js": "^9.30.1",
|
||||||
|
"@types/node": "^24.7.2",
|
||||||
"@types/react": "^19.1.8",
|
"@types/react": "^19.1.8",
|
||||||
"@types/react-dom": "^19.1.6",
|
"@types/react-dom": "^19.1.6",
|
||||||
"@vitejs/plugin-react": "^4.6.0",
|
"@vitejs/plugin-react": "^4.6.0",
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
import { useMsal } from "@azure/msal-react";
|
import { useMsal } from "@azure/msal-react";
|
||||||
import { Navigate, useLocation } from "react-router-dom";
|
import { Navigate, useLocation } from "react-router-dom";
|
||||||
import { ReactNode, useEffect, useState } from "react";
|
import { ReactNode, useEffect, useState } from "react";
|
||||||
import api from "../api";
|
|
||||||
|
|
||||||
interface ProtectedRouteProps {
|
interface ProtectedRouteProps {
|
||||||
children: ReactNode;
|
children: ReactNode;
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,6 @@ import {
|
||||||
import { msalConfig } from "./authConfig";
|
import { msalConfig } from "./authConfig";
|
||||||
import { MsalProvider } from "@azure/msal-react";
|
import { MsalProvider } from "@azure/msal-react";
|
||||||
import { ReactNode, useEffect, useState } from "react";
|
import { ReactNode, useEffect, useState } from "react";
|
||||||
import api from "../api";
|
|
||||||
|
|
||||||
interface AuthProviderProps {
|
interface AuthProviderProps {
|
||||||
children: ReactNode;
|
children: ReactNode;
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@ export function ConnectionsTable({
|
||||||
onRowSelect={onRowSelect}
|
onRowSelect={onRowSelect}
|
||||||
onDelete={onDelete}
|
onDelete={onDelete}
|
||||||
onDeleteMultiple={onDeleteMultiple}
|
onDeleteMultiple={onDeleteMultiple}
|
||||||
actions={actions}
|
actionButtons={actions}
|
||||||
className={styles.connectionsTable}
|
className={styles.connectionsTable}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,6 @@
|
||||||
import { ColumnConfig } from '../FormGenerator';
|
import { ColumnConfig } from '../FormGenerator';
|
||||||
import { EditFieldConfig } from '../ui/Popup';
|
import { EditFieldConfig } from '../ui/Popup';
|
||||||
|
|
||||||
// Import React for component types
|
|
||||||
import React from 'react';
|
|
||||||
|
|
||||||
// Re-export connection-related interfaces from hooks
|
// Re-export connection-related interfaces from hooks
|
||||||
export type { Connection, CreateConnectionData } from '../../hooks/useConnections';
|
export type { Connection, CreateConnectionData } from '../../hooks/useConnections';
|
||||||
import type { Connection } from '../../hooks/useConnections';
|
import type { Connection } from '../../hooks/useConnections';
|
||||||
|
|
@ -37,9 +34,11 @@ export interface ConnectionsErrorDisplayProps {
|
||||||
|
|
||||||
// Table Action Interface
|
// Table Action Interface
|
||||||
export interface TableAction {
|
export interface TableAction {
|
||||||
label: string;
|
type: 'edit' | 'delete' | 'download' | 'view' | 'copy';
|
||||||
onClick?: (connection: Connection) => Promise<void> | void;
|
title?: string | ((connection: Connection) => string);
|
||||||
icon: React.ReactNode | ((connection: Connection) => React.ReactNode);
|
onAction?: (connection: Connection) => Promise<void> | void;
|
||||||
|
disabled?: (connection: Connection) => boolean | { disabled: boolean; message?: string };
|
||||||
|
loading?: (connection: Connection) => boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Connection Status Types
|
// Connection Status Types
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,4 @@
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import { IoIosRefresh, IoIosTrash } from 'react-icons/io';
|
|
||||||
import { MdModeEdit } from 'react-icons/md';
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -441,21 +439,16 @@ export function useConnectionsLogic(): ConnectionsLogicReturn {
|
||||||
// Table actions
|
// Table actions
|
||||||
const tableActions: TableAction[] = [
|
const tableActions: TableAction[] = [
|
||||||
{
|
{
|
||||||
label: t('connections.action.edit', 'Edit'),
|
type: 'edit',
|
||||||
onClick: handleEditConnection,
|
title: t('connections.action.edit', 'Edit'),
|
||||||
icon: <MdModeEdit />
|
onAction: handleEditConnection
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: t('connections.action.update', 'Update'),
|
type: 'delete',
|
||||||
onClick: handleUpdateConnection,
|
title: t('connections.action.delete', 'Delete')
|
||||||
icon: <IoIosRefresh />
|
// onAction is handled by FormGenerator for delete confirmation
|
||||||
},
|
|
||||||
{
|
|
||||||
label: t('connections.action.delete', 'Delete'),
|
|
||||||
icon: <IoIosTrash />,
|
|
||||||
// onClick is handled by FormGenerator for delete confirmation
|
|
||||||
}
|
}
|
||||||
];
|
] as any;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
// Data
|
// Data
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ const FileAttachmentPopup: React.FC<FileAttachmentPopupProps> = ({
|
||||||
const [fileSubTab, setFileSubTab] = useState<'all' | 'uploads' | 'created' | 'shared'>('all');
|
const [fileSubTab, setFileSubTab] = useState<'all' | 'uploads' | 'created' | 'shared'>('all');
|
||||||
const fileInputRef = useRef<HTMLInputElement>(null);
|
const fileInputRef = useRef<HTMLInputElement>(null);
|
||||||
|
|
||||||
const { files: existingFiles, loading: filesLoading } = useUserFiles();
|
const { data: existingFiles, loading: filesLoading } = useUserFiles();
|
||||||
|
|
||||||
const handleDragEnter = (e: React.DragEvent) => {
|
const handleDragEnter = (e: React.DragEvent) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,6 @@ export function CopyActionButton<T = any>({
|
||||||
title,
|
title,
|
||||||
isCopying = false,
|
isCopying = false,
|
||||||
hookData,
|
hookData,
|
||||||
idField = 'id',
|
|
||||||
nameField = 'name',
|
nameField = 'name',
|
||||||
contentField = 'content',
|
contentField = 'content',
|
||||||
loadingStateName = 'creatingPrompt',
|
loadingStateName = 'creatingPrompt',
|
||||||
|
|
|
||||||
|
|
@ -152,9 +152,6 @@ export function DeleteActionButton<T = any>({
|
||||||
const confirmButtonTitle = confirmTitle || t('formgen.delete.confirm', 'Confirm delete');
|
const confirmButtonTitle = confirmTitle || t('formgen.delete.confirm', 'Confirm delete');
|
||||||
const cancelButtonTitle = cancelTitle || t('formgen.delete.cancel', 'Cancel delete');
|
const cancelButtonTitle = cancelTitle || t('formgen.delete.cancel', 'Cancel delete');
|
||||||
|
|
||||||
// Use loading state from hookData if available
|
|
||||||
const isDeletingFromHook = loadingState?.has((row as any)[idField]) || false;
|
|
||||||
|
|
||||||
// Check if ANY deletion is in progress (not just this specific item)
|
// Check if ANY deletion is in progress (not just this specific item)
|
||||||
const isAnyDeletionInProgress = loadingState && loadingState.size > 0;
|
const isAnyDeletionInProgress = loadingState && loadingState.size > 0;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -40,8 +40,6 @@ export function EditActionButton<T = any>({
|
||||||
isEditing = false,
|
isEditing = false,
|
||||||
hookData,
|
hookData,
|
||||||
idField = 'id',
|
idField = 'id',
|
||||||
nameField = 'name',
|
|
||||||
typeField = 'type',
|
|
||||||
operationName = 'handleFileUpdate',
|
operationName = 'handleFileUpdate',
|
||||||
loadingStateName = 'editingFiles',
|
loadingStateName = 'editingFiles',
|
||||||
editFields = [
|
editFields = [
|
||||||
|
|
|
||||||
|
|
@ -165,7 +165,7 @@ function MitgliederTable({ className = '', showAddUser = false, onAddUserClose }
|
||||||
pageSize={10}
|
pageSize={10}
|
||||||
selectable={false}
|
selectable={false}
|
||||||
loading={loading}
|
loading={loading}
|
||||||
actions={actions}
|
actionButtons={actions}
|
||||||
onRefresh={refetch}
|
onRefresh={refetch}
|
||||||
className={styles.mitgliederFormGenerator}
|
className={styles.mitgliederFormGenerator}
|
||||||
getRowDataAttributes={(row) => {
|
getRowDataAttributes={(row) => {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,4 @@
|
||||||
import { useMemo, useState } from 'react';
|
import { useMemo, useState } from 'react';
|
||||||
import { MdModeEdit } from 'react-icons/md';
|
|
||||||
import { IoIosTrash } from 'react-icons/io';
|
|
||||||
|
|
||||||
import { useOrgUsers } from '../../hooks/useUsers';
|
import { useOrgUsers } from '../../hooks/useUsers';
|
||||||
import { useLanguage } from '../../contexts/LanguageContext';
|
import { useLanguage } from '../../contexts/LanguageContext';
|
||||||
|
|
@ -230,16 +228,16 @@ export function useMitgliederLogic(): MitgliederLogicReturn {
|
||||||
// Configure action buttons
|
// Configure action buttons
|
||||||
const actions: UserActionConfig[] = useMemo(() => [
|
const actions: UserActionConfig[] = useMemo(() => [
|
||||||
{
|
{
|
||||||
label: t('users.actions.edit', 'Edit'),
|
type: 'edit',
|
||||||
icon: () => <MdModeEdit />,
|
title: t('users.actions.edit', 'Edit'),
|
||||||
onClick: (row: any) => handleEditUser(row)
|
onAction: (row: any) => handleEditUser(row)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: t('users.actions.delete', 'Delete'),
|
type: 'delete',
|
||||||
icon: () => <IoIosTrash />,
|
title: t('users.actions.delete', 'Delete'),
|
||||||
onClick: (row: any) => handleDeleteUser(row)
|
onAction: (row: any) => handleDeleteUser(row)
|
||||||
}
|
}
|
||||||
], [t]);
|
] as any, [t]);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
// Data
|
// Data
|
||||||
|
|
|
||||||
|
|
@ -10,9 +10,11 @@ export interface MitgliederTableProps {
|
||||||
|
|
||||||
// Action configuration for user actions
|
// Action configuration for user actions
|
||||||
export interface UserActionConfig {
|
export interface UserActionConfig {
|
||||||
label: string;
|
type: 'edit' | 'delete' | 'download' | 'view' | 'copy';
|
||||||
icon: (row: User) => React.ReactElement;
|
title?: string | ((row: User) => string);
|
||||||
onClick: (row: User) => void;
|
onAction?: (row: User) => Promise<void> | void;
|
||||||
|
disabled?: (row: User) => boolean | { disabled: boolean; message?: string };
|
||||||
|
loading?: (row: User) => boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Column configuration for the users table
|
// Column configuration for the users table
|
||||||
|
|
|
||||||
|
|
@ -73,7 +73,7 @@ function PromptsTable({ className = '' }: PromptsTableProps) {
|
||||||
selectable={true}
|
selectable={true}
|
||||||
isRowSelectable={isPromptSelectable}
|
isRowSelectable={isPromptSelectable}
|
||||||
loading={loading}
|
loading={loading}
|
||||||
actions={actions}
|
actionButtons={actions}
|
||||||
onDelete={handleDeleteSingle}
|
onDelete={handleDeleteSingle}
|
||||||
onDeleteMultiple={handleDeleteMultiple}
|
onDeleteMultiple={handleDeleteMultiple}
|
||||||
onRefresh={refetch}
|
onRefresh={refetch}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,4 @@
|
||||||
import { useState, useMemo } from 'react';
|
import { useState, useMemo } from 'react';
|
||||||
import { IoIosTrash, IoIosCopy } from 'react-icons/io';
|
|
||||||
import { MdModeEdit } from 'react-icons/md';
|
|
||||||
|
|
||||||
import { usePrompts, usePromptOperations, Prompt } from '../../hooks/usePrompts';
|
import { usePrompts, usePromptOperations, Prompt } from '../../hooks/usePrompts';
|
||||||
import { useLanguage } from '../../contexts/LanguageContext';
|
import { useLanguage } from '../../contexts/LanguageContext';
|
||||||
|
|
@ -260,44 +258,31 @@ export function usePromptsLogic(): PromptsLogicReturn {
|
||||||
// Configure action buttons
|
// Configure action buttons
|
||||||
const actions: PromptActionConfig[] = useMemo(() => [
|
const actions: PromptActionConfig[] = useMemo(() => [
|
||||||
{
|
{
|
||||||
label: t('prompts.action.edit', 'Edit'),
|
type: 'edit',
|
||||||
icon: (_row: Prompt) => {
|
title: t('prompts.action.edit', 'Edit'),
|
||||||
return <MdModeEdit />;
|
onAction: (row: Prompt) => {
|
||||||
},
|
|
||||||
onClick: (row: Prompt) => {
|
|
||||||
handleEditPrompt(row);
|
handleEditPrompt(row);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: t('prompts.action.copy', 'Copy'),
|
type: 'copy',
|
||||||
icon: (_row: Prompt) => {
|
title: t('prompts.action.copy', 'Copy'),
|
||||||
return <IoIosCopy />;
|
onAction: (row: Prompt) => {
|
||||||
},
|
|
||||||
onClick: (row: Prompt) => {
|
|
||||||
handleCopyPrompt(row);
|
handleCopyPrompt(row);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: (row: Prompt) => {
|
type: 'delete',
|
||||||
|
title: (row: Prompt) => {
|
||||||
const isDeletable = isPromptDeletable(row);
|
const isDeletable = isPromptDeletable(row);
|
||||||
return isDeletable
|
return isDeletable
|
||||||
? t('prompts.action.delete', 'Delete')
|
? t('prompts.action.delete', 'Delete')
|
||||||
: t('prompts.action.delete.disabled', 'No permission to delete prompt');
|
: t('prompts.action.delete.disabled', 'No permission to delete prompt');
|
||||||
},
|
},
|
||||||
icon: (row: Prompt) => {
|
disabled: (row: Prompt) => !isPromptDeletable(row)
|
||||||
const isDeletable = isPromptDeletable(row);
|
// onAction is handled by FormGenerator for delete confirmation
|
||||||
return (
|
|
||||||
<IoIosTrash
|
|
||||||
style={{
|
|
||||||
opacity: isDeletable ? 1 : 0.4,
|
|
||||||
cursor: isDeletable ? 'pointer' : 'not-allowed'
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
},
|
|
||||||
// onClick is handled by FormGenerator for delete confirmation
|
|
||||||
},
|
},
|
||||||
], [t, deletingPrompts, handleDeletePrompt, handleEditPrompt, handleCopyPrompt]);
|
] as any, [t, deletingPrompts, handleDeletePrompt, handleEditPrompt, handleCopyPrompt]);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
// Data
|
// Data
|
||||||
|
|
|
||||||
|
|
@ -17,9 +17,11 @@ export interface PromptsTableProps {
|
||||||
|
|
||||||
// Action configuration for prompt actions
|
// Action configuration for prompt actions
|
||||||
export interface PromptActionConfig {
|
export interface PromptActionConfig {
|
||||||
label: string | ((row: Prompt) => string);
|
type: 'edit' | 'delete' | 'download' | 'view' | 'copy';
|
||||||
icon: (row: Prompt) => React.ReactElement;
|
title?: string | ((row: Prompt) => string);
|
||||||
onClick?: (row: Prompt) => void;
|
onAction?: (row: Prompt) => Promise<void> | void;
|
||||||
|
disabled?: (row: Prompt) => boolean | { disabled: boolean; message?: string };
|
||||||
|
loading?: (row: Prompt) => boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Column configuration for the prompts table
|
// Column configuration for the prompts table
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import React, { useState, useEffect } from 'react';
|
import { useState, useEffect } from 'react';
|
||||||
import { IoIosBusiness, IoIosContact, IoIosTime, IoIosRefresh } from 'react-icons/io';
|
import { IoIosBusiness, IoIosContact, IoIosTime, IoIosRefresh } from 'react-icons/io';
|
||||||
import sharedStyles from '../../core/PageManager/pages.module.css';
|
import sharedStyles from '../../core/PageManager/pages.module.css';
|
||||||
import styles from './SpeechSettings.module.css';
|
import styles from './SpeechSettings.module.css';
|
||||||
|
|
|
||||||
|
|
@ -62,7 +62,7 @@ export function TestSharepointTable({
|
||||||
showPageSizeSelector={true}
|
showPageSizeSelector={true}
|
||||||
selectable={false}
|
selectable={false}
|
||||||
onRowClick={onRowClick}
|
onRowClick={onRowClick}
|
||||||
actions={actualActions}
|
actionButtons={actualActions}
|
||||||
className={styles.sharepointFormGenerator}
|
className={styles.sharepointFormGenerator}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ function WorkflowsTable({ className = '' }: WorkflowsTableProps) {
|
||||||
pagination={true}
|
pagination={true}
|
||||||
pageSize={10}
|
pageSize={10}
|
||||||
loading={logic.loading}
|
loading={logic.loading}
|
||||||
actions={logic.actions}
|
actionButtons={logic.actions}
|
||||||
onDelete={logic.handleDeleteSingle}
|
onDelete={logic.handleDeleteSingle}
|
||||||
onDeleteMultiple={logic.handleDeleteMultiple}
|
onDeleteMultiple={logic.handleDeleteMultiple}
|
||||||
onRefresh={logic.refetch}
|
onRefresh={logic.refetch}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import React, { useState, useEffect } from 'react';
|
import { useState, useEffect } from 'react';
|
||||||
import { IoIosBusiness, IoIosContact, IoIosTime, IoIosRefresh } from 'react-icons/io';
|
import { IoIosBusiness, IoIosContact, IoIosTime, IoIosRefresh } from 'react-icons/io';
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
import styles from './settingsSpeech.module.css';
|
import styles from './settingsSpeech.module.css';
|
||||||
|
|
@ -34,7 +34,6 @@ function SettingsSpeech({ onDataUpdate }: SettingsSpeechProps) {
|
||||||
const [isLoading, setIsLoading] = useState(true);
|
const [isLoading, setIsLoading] = useState(true);
|
||||||
const [isSaving, setIsSaving] = useState(false);
|
const [isSaving, setIsSaving] = useState(false);
|
||||||
const [saveMessage, setSaveMessage] = useState<{ type: 'success' | 'error', text: string } | null>(null);
|
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
|
// Load data from localStorage on component mount
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
@ -94,17 +93,6 @@ function SettingsSpeech({ onDataUpdate }: SettingsSpeechProps) {
|
||||||
setSaveMessage(null);
|
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 () => {
|
const handleSave = async () => {
|
||||||
if (!formData) return;
|
if (!formData) return;
|
||||||
|
|
@ -200,8 +188,6 @@ function SettingsSpeech({ onDataUpdate }: SettingsSpeechProps) {
|
||||||
className={styles.formInput}
|
className={styles.formInput}
|
||||||
value={formData.mandate_general.company_name}
|
value={formData.mandate_general.company_name}
|
||||||
onChange={(e) => handleInputChange('mandate_general.company_name', e.target.value)}
|
onChange={(e) => handleInputChange('mandate_general.company_name', e.target.value)}
|
||||||
onFocus={() => handleFocus('company_name')}
|
|
||||||
onBlur={() => handleBlur('company_name')}
|
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -215,8 +201,6 @@ function SettingsSpeech({ onDataUpdate }: SettingsSpeechProps) {
|
||||||
className={styles.formInput}
|
className={styles.formInput}
|
||||||
value={formData.mandate_general.industry}
|
value={formData.mandate_general.industry}
|
||||||
onChange={(e) => handleInputChange('mandate_general.industry', e.target.value)}
|
onChange={(e) => handleInputChange('mandate_general.industry', e.target.value)}
|
||||||
onFocus={() => handleFocus('industry')}
|
|
||||||
onBlur={() => handleBlur('industry')}
|
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -240,8 +224,6 @@ function SettingsSpeech({ onDataUpdate }: SettingsSpeechProps) {
|
||||||
className={styles.formInput}
|
className={styles.formInput}
|
||||||
value={formData.mandate_general.contact_info.email}
|
value={formData.mandate_general.contact_info.email}
|
||||||
onChange={(e) => handleInputChange('mandate_general.contact_info.email', e.target.value)}
|
onChange={(e) => handleInputChange('mandate_general.contact_info.email', e.target.value)}
|
||||||
onFocus={() => handleFocus('email')}
|
|
||||||
onBlur={() => handleBlur('email')}
|
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -255,8 +237,6 @@ function SettingsSpeech({ onDataUpdate }: SettingsSpeechProps) {
|
||||||
className={styles.formInput}
|
className={styles.formInput}
|
||||||
value={formData.mandate_general.contact_info.phone}
|
value={formData.mandate_general.contact_info.phone}
|
||||||
onChange={(e) => handleInputChange('mandate_general.contact_info.phone', e.target.value)}
|
onChange={(e) => handleInputChange('mandate_general.contact_info.phone', e.target.value)}
|
||||||
onFocus={() => handleFocus('phone')}
|
|
||||||
onBlur={() => handleBlur('phone')}
|
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -272,8 +252,6 @@ function SettingsSpeech({ onDataUpdate }: SettingsSpeechProps) {
|
||||||
className={styles.formInput}
|
className={styles.formInput}
|
||||||
value={formData.mandate_general.contact_info.street}
|
value={formData.mandate_general.contact_info.street}
|
||||||
onChange={(e) => handleInputChange('mandate_general.contact_info.street', e.target.value)}
|
onChange={(e) => handleInputChange('mandate_general.contact_info.street', e.target.value)}
|
||||||
onFocus={() => handleFocus('street')}
|
|
||||||
onBlur={() => handleBlur('street')}
|
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -287,8 +265,6 @@ function SettingsSpeech({ onDataUpdate }: SettingsSpeechProps) {
|
||||||
className={styles.formInput}
|
className={styles.formInput}
|
||||||
value={formData.mandate_general.contact_info.postal_code}
|
value={formData.mandate_general.contact_info.postal_code}
|
||||||
onChange={(e) => handleInputChange('mandate_general.contact_info.postal_code', e.target.value)}
|
onChange={(e) => handleInputChange('mandate_general.contact_info.postal_code', e.target.value)}
|
||||||
onFocus={() => handleFocus('postal_code')}
|
|
||||||
onBlur={() => handleBlur('postal_code')}
|
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -304,8 +280,6 @@ function SettingsSpeech({ onDataUpdate }: SettingsSpeechProps) {
|
||||||
className={styles.formInput}
|
className={styles.formInput}
|
||||||
value={formData.mandate_general.contact_info.city}
|
value={formData.mandate_general.contact_info.city}
|
||||||
onChange={(e) => handleInputChange('mandate_general.contact_info.city', e.target.value)}
|
onChange={(e) => handleInputChange('mandate_general.contact_info.city', e.target.value)}
|
||||||
onFocus={() => handleFocus('city')}
|
|
||||||
onBlur={() => handleBlur('city')}
|
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -319,8 +293,6 @@ function SettingsSpeech({ onDataUpdate }: SettingsSpeechProps) {
|
||||||
className={styles.formInput}
|
className={styles.formInput}
|
||||||
value={formData.mandate_general.contact_info.country}
|
value={formData.mandate_general.contact_info.country}
|
||||||
onChange={(e) => handleInputChange('mandate_general.contact_info.country', e.target.value)}
|
onChange={(e) => handleInputChange('mandate_general.contact_info.country', e.target.value)}
|
||||||
onFocus={() => handleFocus('country')}
|
|
||||||
onBlur={() => handleBlur('country')}
|
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -344,8 +316,6 @@ function SettingsSpeech({ onDataUpdate }: SettingsSpeechProps) {
|
||||||
className={styles.formInput}
|
className={styles.formInput}
|
||||||
value={formData.mandate_general.business_hours}
|
value={formData.mandate_general.business_hours}
|
||||||
onChange={(e) => handleInputChange('mandate_general.business_hours', e.target.value)}
|
onChange={(e) => handleInputChange('mandate_general.business_hours', e.target.value)}
|
||||||
onFocus={() => handleFocus('business_hours')}
|
|
||||||
onBlur={() => handleBlur('business_hours')}
|
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -358,8 +328,6 @@ function SettingsSpeech({ onDataUpdate }: SettingsSpeechProps) {
|
||||||
className={styles.formSelect}
|
className={styles.formSelect}
|
||||||
value={formData.mandate_general.timezone}
|
value={formData.mandate_general.timezone}
|
||||||
onChange={(e) => handleInputChange('mandate_general.timezone', e.target.value)}
|
onChange={(e) => handleInputChange('mandate_general.timezone', e.target.value)}
|
||||||
onFocus={() => handleFocus('timezone')}
|
|
||||||
onBlur={() => handleBlur('timezone')}
|
|
||||||
required
|
required
|
||||||
>
|
>
|
||||||
<option value="">{t('speech.signup.select_timezone')}</option>
|
<option value="">{t('speech.signup.select_timezone')}</option>
|
||||||
|
|
|
||||||
|
|
@ -3,9 +3,6 @@ import { useLanguage, Language } from '../../contexts/LanguageContext';
|
||||||
import { useCurrentUser, useUser, User } from '../../hooks/useUsers';
|
import { useCurrentUser, useUser, User } from '../../hooks/useUsers';
|
||||||
import styles from './settingsUser.module.css';
|
import styles from './settingsUser.module.css';
|
||||||
|
|
||||||
// Add a check to ensure we're in the right context
|
|
||||||
const isClient = typeof window !== 'undefined';
|
|
||||||
|
|
||||||
interface SettingsUserProps {
|
interface SettingsUserProps {
|
||||||
className?: string;
|
className?: string;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -935,7 +935,7 @@ export function useLogout() {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Call logout endpoint to clear JWT tokens on server
|
// Call logout endpoint to clear JWT tokens on server
|
||||||
const logoutResponse = await api.post('/api/local/logout');
|
await api.post('/api/local/logout');
|
||||||
|
|
||||||
console.log('✅ Logout API call completed, waiting for browser to process cookies...');
|
console.log('✅ Logout API call completed, waiting for browser to process cookies...');
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -151,7 +151,7 @@ export function useCurrentUser() {
|
||||||
logoutEndpoint = '/api/local/logout';
|
logoutEndpoint = '/api/local/logout';
|
||||||
}
|
}
|
||||||
|
|
||||||
const logoutResponse = await request({
|
await request({
|
||||||
url: logoutEndpoint,
|
url: logoutEndpoint,
|
||||||
method: 'post'
|
method: 'post'
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,6 @@ import { useState, useEffect } from 'react';
|
||||||
import sharedStyles from '../../core/PageManager/pages.module.css';
|
import sharedStyles from '../../core/PageManager/pages.module.css';
|
||||||
import { useLanguage } from '../../contexts/LanguageContext';
|
import { useLanguage } from '../../contexts/LanguageContext';
|
||||||
import { FormGenerator, ColumnConfig } from '../../components/FormGenerator/FormGenerator';
|
import { FormGenerator, ColumnConfig } from '../../components/FormGenerator/FormGenerator';
|
||||||
import { IoIosEye, IoIosDownload } from 'react-icons/io';
|
|
||||||
|
|
||||||
interface CallTranscript {
|
interface CallTranscript {
|
||||||
id: string;
|
id: string;
|
||||||
|
|
@ -235,22 +234,22 @@ function SpeechTranscripts() {
|
||||||
// Handle row click - could open a modal with transcript details
|
// Handle row click - could open a modal with transcript details
|
||||||
console.log('Selected transcript:', transcript);
|
console.log('Selected transcript:', transcript);
|
||||||
}}
|
}}
|
||||||
actions={[
|
actionButtons={[
|
||||||
{
|
{
|
||||||
label: t('speech.transcripts.view', 'View'),
|
type: 'view',
|
||||||
onClick: (transcript) => {
|
title: t('speech.transcripts.view', 'View'),
|
||||||
|
onAction: (transcript: CallTranscript) => {
|
||||||
// Handle view action
|
// Handle view action
|
||||||
console.log('View transcript:', transcript);
|
console.log('View transcript:', transcript);
|
||||||
},
|
}
|
||||||
icon: <IoIosEye />
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: t('speech.transcripts.download', 'Download'),
|
type: 'download',
|
||||||
onClick: (transcript) => {
|
title: t('speech.transcripts.download', 'Download'),
|
||||||
|
onAction: (transcript: CallTranscript) => {
|
||||||
// Handle download action
|
// Handle download action
|
||||||
console.log('Download transcript:', transcript);
|
console.log('Download transcript:', transcript);
|
||||||
},
|
}
|
||||||
icon: <IoIosDownload />
|
|
||||||
}
|
}
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { PrivilegeChecker } from '../components/PageManager/pageConfigInterface';
|
import { PrivilegeChecker } from '../core/PageManager/pageInterface';
|
||||||
|
|
||||||
// Function to get current user privilege from localStorage (where it's cached)
|
// Function to get current user privilege from localStorage (where it's cached)
|
||||||
const getCurrentUserPrivilege = (): string | null => {
|
const getCurrentUserPrivilege = (): string | null => {
|
||||||
|
|
|
||||||
|
|
@ -18,9 +18,6 @@ export default defineConfig(({ mode }) => {
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
envPrefix: 'VITE_',
|
envPrefix: 'VITE_',
|
||||||
server: {
|
|
||||||
https: false,
|
|
||||||
},
|
|
||||||
css: {
|
css: {
|
||||||
modules: {
|
modules: {
|
||||||
scopeBehaviour: 'local', // Default behavior for CSS modules
|
scopeBehaviour: 'local', // Default behavior for CSS modules
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue