From 9d5308206eb6e8d741f1535cc4e9d93414b93b8e Mon Sep 17 00:00:00 2001 From: Ida Dittrich Date: Fri, 22 Aug 2025 12:00:05 +0200 Subject: [PATCH] added prompt and user page --- README.md | Bin 46 -> 6558 bytes .../Connections/ConnectionsTable.tsx | 10 +- .../Connections/connectionsInterfaces.ts | 3 + .../Connections/connectionsLogic.tsx | 15 + .../DashboardChat/DashboardChatArea.tsx | 3 +- .../DashboardChatAreaMessageItem.tsx | 2 + .../FormGenerator/FormGenerator.tsx | 2 +- .../Mitglieder/MitgliederItem.module.css | 57 ---- src/components/Mitglieder/MitgliederItem.tsx | 32 -- .../DeletePopUp.module.css | 92 ------ .../MitgliederItemDelete/DeletePopUp.tsx | 88 ----- .../MitgliederItemDelete.module.css | 33 -- .../MitgliederItemDelete.tsx | 37 --- .../MitgliederItemEdit/EditPopUp.module.css | 89 ------ .../MitgliederItemEdit/EditPopUp.tsx | 152 --------- .../MitgliederItemEdit.module.css | 12 - .../MitgliederItemEdit/MitgliederItemEdit.tsx | 36 --- .../Mitglieder/MitgliederTable.module.css | 64 ++++ src/components/Mitglieder/MitgliederTable.tsx | 50 +++ src/components/Mitglieder/index.ts | 3 + src/components/Mitglieder/mitgliederLogic.tsx | 107 +++++++ src/components/Mitglieder/mitgliederTypes.ts | 44 +++ src/components/PageManager/pageConfigs.ts | 26 +- src/components/Popup/EditForm.module.css | 29 ++ src/components/Popup/EditForm.tsx | 66 +++- .../Prompts/PromptsTable.module.css | 76 +++++ src/components/Prompts/PromptsTable.tsx | 82 +++++ src/components/Prompts/index.ts | 3 + src/components/Prompts/promptsLogic.tsx | 301 ++++++++++++++++++ src/components/Prompts/promptsTypes.ts | 66 ++++ src/components/Sidebar/Sidebar.tsx | 3 +- src/hooks/useApi.ts | 20 +- src/hooks/usePrompts.ts | 133 +------- src/hooks/useUsers.ts | 14 +- src/locales/de.ts | 48 +++ src/locales/en.ts | 50 ++- src/locales/fr.ts | 45 +++ src/main.tsx | 5 +- src/pages/Home/Connections.tsx | 12 +- src/pages/Home/HomeStyles/Dateien.module.css | 23 -- src/pages/Home/HomeStyles/Prompts.module.css | 0 src/pages/Home/Prompts.tsx | 139 ++++++++ src/pages/Home/TeamBereich.tsx | 55 +--- 43 files changed, 1275 insertions(+), 852 deletions(-) delete mode 100644 src/components/Mitglieder/MitgliederItem.module.css delete mode 100644 src/components/Mitglieder/MitgliederItem.tsx delete mode 100644 src/components/Mitglieder/MitgliederItemDelete/DeletePopUp.module.css delete mode 100644 src/components/Mitglieder/MitgliederItemDelete/DeletePopUp.tsx delete mode 100644 src/components/Mitglieder/MitgliederItemDelete/MitgliederItemDelete.module.css delete mode 100644 src/components/Mitglieder/MitgliederItemDelete/MitgliederItemDelete.tsx delete mode 100644 src/components/Mitglieder/MitgliederItemEdit/EditPopUp.module.css delete mode 100644 src/components/Mitglieder/MitgliederItemEdit/EditPopUp.tsx delete mode 100644 src/components/Mitglieder/MitgliederItemEdit/MitgliederItemEdit.module.css delete mode 100644 src/components/Mitglieder/MitgliederItemEdit/MitgliederItemEdit.tsx create mode 100644 src/components/Mitglieder/MitgliederTable.module.css create mode 100644 src/components/Mitglieder/MitgliederTable.tsx create mode 100644 src/components/Mitglieder/index.ts create mode 100644 src/components/Mitglieder/mitgliederLogic.tsx create mode 100644 src/components/Mitglieder/mitgliederTypes.ts create mode 100644 src/components/Prompts/PromptsTable.module.css create mode 100644 src/components/Prompts/PromptsTable.tsx create mode 100644 src/components/Prompts/index.ts create mode 100644 src/components/Prompts/promptsLogic.tsx create mode 100644 src/components/Prompts/promptsTypes.ts create mode 100644 src/pages/Home/HomeStyles/Prompts.module.css create mode 100644 src/pages/Home/Prompts.tsx diff --git a/README.md b/README.md index 36fc52810a1b41477b92fbfe6fd3ceafbc010633..1384bda5b52a75a88ab47214065c16c55a72781d 100644 GIT binary patch literal 6558 zcmcgw+fLg+5Z&iW{RdY(v_+-)1_Tr#l@bZ6zSiVoEOJ4)G(w?2(GPBW&a9X9UhLRO zKv806?L9kl=FIHa|Nb7RL|v%|HBb|r-KZ&kPx1R+&DC4=M!rWF`=W9+!d;2#su_;I z@PD9I_@B$ng}RfgJseZD!1xNsIgWGuOEG7G>wWxBaX*i_Tzx36Pi8nya9ln6L%$9%dZEVfoL-Ib)oT*%7(QO$ zcv9G8nRtp^O%zA3u{v#CidP@7{uGD(R$c za5%v?gVjm#uP-ra%EDL>>>R5!&9<8jdaN7)t+_7Laa}0Y_`4rutCworHFTn@m##_| z$T1tSc7A-{=*9k4J4JSXl?*?Vyn0y=|Ge`R!dhqa!-|x_id(7l>2sAzBtK0(W_Ibl zz|}=nMGrOl9oacRwl>RAR&9N^)n%x@P$T7eYpMN2adi>mbd?|d?Qp8%x*b|9w=9yW zmt}84)=ihtjP)UEDR=ev8hfs#zL0Mt_>K?PTjJA}0eG1j}8zP3WE#q+~ z(zd#>T|&)0@qryq%uYYj28TXZq1O9e74_Yb>p9SU+yYUuF`@$84AoUIWTGD1XQCs~ zUxD2bRPa(!>_8>uUbdZIq59bwPr=6nblfZhxW1iX)(_c>>AmUPka>3|byyy86&|z2 z*K~Qd)^&Mg6JC{`%NT7?!?>JCC1E$-Lu7Oh+$=u2XY^;aDMe%ge3UhOavRI-c()uj>8X-|G7L)a7ZD4OHz9=yay;vDdKbtuV6r>0;&0 zVWwF<$L^q-NYT#jR4fj@J}>W3%=4p~DWk2bV+c&hD6> z8>|w|da&2Eu=CtA>&!F#={EM$$7|WYm#C2Xok@ac+9@hM-y4RNG8TPigTCKn2A@Wo zMRyY(`^c<#hT$_{Gt@BS$~H3Y1}D~sh3`Vjvw5E3%Xd`abE_=MJb^7bCovNO69@HDlJ!a`ftXk7>)| zw25P!@pJG@E$~^p3D;DOx!?3s%-(EkR$N5wktJjQ{`u diff --git a/src/components/Connections/ConnectionsTable.tsx b/src/components/Connections/ConnectionsTable.tsx index 5ea1543..6251469 100644 --- a/src/components/Connections/ConnectionsTable.tsx +++ b/src/components/Connections/ConnectionsTable.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +// import React from 'react'; import { FormGenerator } from '../FormGenerator'; import styles from './ConnectionsTable.module.css'; import { ConnectionsTableProps } from './connectionsInterfaces'; @@ -11,7 +11,9 @@ export function ConnectionsTable({ isLoading = false, isConnecting = false, isDisconnecting = false, - onRowSelect + onRowSelect, + onDelete, + onDeleteMultiple }: ConnectionsTableProps) { const { t } = useLanguage(); @@ -30,8 +32,10 @@ export function ConnectionsTable({ resizable={true} pagination={true} pageSize={10} - selectable={false} + selectable={true} onRowSelect={onRowSelect} + onDelete={onDelete} + onDeleteMultiple={onDeleteMultiple} actions={actions} className={styles.connectionsTable} /> diff --git a/src/components/Connections/connectionsInterfaces.ts b/src/components/Connections/connectionsInterfaces.ts index 6003b51..61b85cb 100644 --- a/src/components/Connections/connectionsInterfaces.ts +++ b/src/components/Connections/connectionsInterfaces.ts @@ -16,6 +16,8 @@ export interface ConnectionsTableProps { isConnecting?: boolean; isDisconnecting?: boolean; onRowSelect?: (selectedRows: Connection[]) => void; + onDelete?: (connection: Connection) => Promise; + onDeleteMultiple?: (connections: Connection[]) => Promise; } export interface ConnectionEditModalProps { @@ -49,6 +51,7 @@ export interface ConnectionHandlers { handleConnect: (connection: Connection) => Promise; handleDisconnect: (connection: Connection) => Promise; handleDelete: (connection: Connection) => Promise; + handleDeleteMultiple: (connections: Connection[]) => Promise; handleConnectOrDisconnect: (connection: Connection) => Promise; handleEditConnection: (connection: Connection) => Promise; handleSaveConnection: (updatedConnection: Connection) => Promise; diff --git a/src/components/Connections/connectionsLogic.tsx b/src/components/Connections/connectionsLogic.tsx index 8268ae6..872f176 100644 --- a/src/components/Connections/connectionsLogic.tsx +++ b/src/components/Connections/connectionsLogic.tsx @@ -254,6 +254,20 @@ export function useConnectionsLogic(): ConnectionsLogicReturn { } }; + const handleDeleteMultiple = async (connections: Connection[]) => { + const confirmMessage = t('connections.confirm_delete_multiple', 'Are you sure you want to delete {count} connections?').replace('{count}', connections.length.toString()); + + if (window.confirm(confirmMessage)) { + try { + // Delete all connections in parallel + await Promise.all(connections.map(connection => deleteConnection(connection.id))); + await fetchConnections(); + } catch (error) { + console.error('Error deleting multiple connections:', error); + } + } + }; + const handleConnectOrDisconnect = async (connection: Connection) => { if (connection.status === 'active') { await handleDisconnect(connection); @@ -331,6 +345,7 @@ export function useConnectionsLogic(): ConnectionsLogicReturn { handleConnect, handleDisconnect, handleDelete, + handleDeleteMultiple, handleConnectOrDisconnect, handleEditConnection, handleSaveConnection, diff --git a/src/components/Dashboard/DashboardChat/DashboardChatArea.tsx b/src/components/Dashboard/DashboardChat/DashboardChatArea.tsx index bdc84fb..60c2fba 100644 --- a/src/components/Dashboard/DashboardChat/DashboardChatArea.tsx +++ b/src/components/Dashboard/DashboardChat/DashboardChatArea.tsx @@ -23,10 +23,11 @@ const DashboardChatArea: React.FC = ({ /> - {/* Top Right: File Preview */} + {/*Top Right: File Preview (disabled for now)
+ */} {/* Bottom Left: Input Area */}
diff --git a/src/components/Dashboard/DashboardChat/DashboardChatAreaMessageItem.tsx b/src/components/Dashboard/DashboardChat/DashboardChatAreaMessageItem.tsx index 2e75440..f868c14 100644 --- a/src/components/Dashboard/DashboardChat/DashboardChatAreaMessageItem.tsx +++ b/src/components/Dashboard/DashboardChat/DashboardChatAreaMessageItem.tsx @@ -110,6 +110,7 @@ const MessageItem: React.FC = ({ message, onFilePreview }) => )}
+ {/* Preview and Download buttons disabled for now
+ */} ))} diff --git a/src/components/FormGenerator/FormGenerator.tsx b/src/components/FormGenerator/FormGenerator.tsx index aa20456..802673a 100644 --- a/src/components/FormGenerator/FormGenerator.tsx +++ b/src/components/FormGenerator/FormGenerator.tsx @@ -397,7 +397,7 @@ export function FormGenerator>({ title={t('formgen.delete.multiple', `Delete ${selectedRows.size} selected items`)} > - {t('formgen.delete.multiple', `Delete All (${selectedRows.size})`)} + {t('formgen.delete.multiple', `Delete ${selectedRows.size} selected items`).replace('{count}', selectedRows.size.toString())} )} diff --git a/src/components/Mitglieder/MitgliederItem.module.css b/src/components/Mitglieder/MitgliederItem.module.css deleted file mode 100644 index 3b6cf50..0000000 --- a/src/components/Mitglieder/MitgliederItem.module.css +++ /dev/null @@ -1,57 +0,0 @@ -.memberItem { - display: flex; - align-items: center; - height: 70px; - padding: 0px 16px; - justify-content: space-between; - color: var(--color-text); - font-family: var(--font-family); - } - - .userProfile { - margin-right: 12px; - } - - .profileIcon { - font-size: 36px; - color: var(--color-gray-disabled); - } - - .userInfo { - display: grid; - grid-template-columns: 200px 250px 100px; - gap: 16px; - flex-grow: 1; - align-items: center; - } - - .userName { - margin: 0; - font-size: 14px; - color: var(--color-text); - font-family: var(--font-family); - } - - .userEmail, - .userRole { - margin: 0; - font-size: 12px; - font-weight: light; - color: var(--color-gray); - font-family: var(--font-family); - } - - .actions { - display: flex; - align-items: center; - justify-content: center; - } - - .editBtn:hover { - color: var(--color-secondary); - } - - .deleteBtn:hover { - color: var(--color-red); - } - \ No newline at end of file diff --git a/src/components/Mitglieder/MitgliederItem.tsx b/src/components/Mitglieder/MitgliederItem.tsx deleted file mode 100644 index b41d6aa..0000000 --- a/src/components/Mitglieder/MitgliederItem.tsx +++ /dev/null @@ -1,32 +0,0 @@ -import { FaUserCircle } from "react-icons/fa"; -import styles from "./MitgliederItem.module.css"; -import MitgliederItemDelete from "./MitgliederItemDelete/MitgliederItemDelete"; -import MitgliederItemEdit from "./MitgliederItemEdit/MitgliederItemEdit"; -import { User } from "../../hooks/useUsers"; - -type MitgliederItemProps = { - user: User; - refetchUsers: () => Promise; - totalUsers: number; - }; - - const MitgliederItem = ({ user, refetchUsers, totalUsers }: MitgliederItemProps) => { - return ( -
  • -
    - -
    -
    - {user.fullName || user.username} - {user.email} - {user.privilege} -
    -
    - - -
    -
  • - ); - }; - - export default MitgliederItem; \ No newline at end of file diff --git a/src/components/Mitglieder/MitgliederItemDelete/DeletePopUp.module.css b/src/components/Mitglieder/MitgliederItemDelete/DeletePopUp.module.css deleted file mode 100644 index b529250..0000000 --- a/src/components/Mitglieder/MitgliederItemDelete/DeletePopUp.module.css +++ /dev/null @@ -1,92 +0,0 @@ -.popupHeader { - display: flex; - justify-content: space-between; - align-items: center; - margin-top:10px; - margin-left: 10px; - margin-right: 10px; - margin-bottom: 5px; - width: 300px; - height: 20px; - color: gray; - font-size: 10px; - -} - -.closeButton { - display: flex; - align-items: center; - background: none; - border: none; - cursor: pointer; - width: 20px; /* Increased button size */ - height: 20px; - line-height: 0; - padding: 0; - margin:0; - -} - -.closeIcon { - width: 100%; /* Make the icon fill the button's width */ - height: 100%; - padding: 0; - margin:0; - display: block; -} - -.horizontalLineLight { - width: 100%; - background-color: #F1F1F1; - height: 1px; -} - -.userInfo { - display: grid; - grid-column: 1; - padding: none; - margin: none; - align-items: center; - justify-content: center; /* Center horizontally */ -} - -.userInfoParagraph{ - display: flex; - color: gray; - font-size: 10px; - margin:0px; - justify-content: center; - gap: 10px; -} -.userInfo h2{ - display: flex; - justify-content: center; - margin: 0; - margin-top:10px; - justify-content: center; -} - -.submitButtonDiv { - margin: 10px; - display: flex; /* Use Flexbox */ - justify-content: center; /* Center horizontally */ - align-items: center; -} -.submitButton { - background: none; - border: 1px solid black; - border-radius: 5px; - padding: 5px 20px; /* Optional: Adds some padding for better button size */ - cursor: pointer; - width: 80% -} - -.submitButton:hover { - background: rgb(168, 18, 18); - border: 1px solid rgb(168, 18, 18); - border-radius: 5px; - padding: 5px 20px; /* Optional: Adds some padding for better button size */ - cursor: pointer; - color: white; - transition: 0.2s; -} \ No newline at end of file diff --git a/src/components/Mitglieder/MitgliederItemDelete/DeletePopUp.tsx b/src/components/Mitglieder/MitgliederItemDelete/DeletePopUp.tsx deleted file mode 100644 index 925ad7d..0000000 --- a/src/components/Mitglieder/MitgliederItemDelete/DeletePopUp.tsx +++ /dev/null @@ -1,88 +0,0 @@ -import { IoCloseOutline } from "react-icons/io5"; -import styles from "./DeletePopUp.module.css"; -import { User, useOrgUsers } from "../../../hooks/useUsers"; -import { useState } from "react"; - -type DeletePopUpProps = { - closePopup: () => void; - refetchUsers: () => Promise; - user: User; -}; - -const DeletePopUp = ({ closePopup, refetchUsers, user }: DeletePopUpProps) => { - const { deleteUser } = useOrgUsers(); - const [isDeleting, setIsDeleting] = useState(false); - const [error, setError] = useState(null); - - const handleDelete = async () => { - setIsDeleting(true); - setError(null); - - try { - await deleteUser(user.id); - // Refresh the users list and close the popup - await refetchUsers(); - closePopup(); - } catch (error: any) { - setError(error.message || "Failed to delete user"); - setIsDeleting(false); - } - }; - - return ( -
    -
    -
    -

    Delete User...

    - - -
    -
    - {error &&
    {error}
    } -
    -

    {user.fullName || user.username}

    -
    -

    Email: {user.email}

    -

    Privilege: {user.privilege}

    -
    -
    -
    -
    - -
    - -
    -
    - ) -} - -const popupStyles: { overlay: React.CSSProperties; popup: React.CSSProperties } = { - overlay: { - position: "fixed", - top: 0, - left: 0, - right: 0, - bottom: 0, - backgroundColor: "rgba(0,0,0,0.5)", - display: "flex", - justifyContent: "center", - alignItems: "center", - - }, - popup: { - backgroundColor: "#fff", - borderRadius: "8px", - boxShadow: "0 5px 15px rgba(0,0,0,0.3)", - position: "relative" - } -}; - -export default DeletePopUp; \ No newline at end of file diff --git a/src/components/Mitglieder/MitgliederItemDelete/MitgliederItemDelete.module.css b/src/components/Mitglieder/MitgliederItemDelete/MitgliederItemDelete.module.css deleted file mode 100644 index 6a4c4bf..0000000 --- a/src/components/Mitglieder/MitgliederItemDelete/MitgliederItemDelete.module.css +++ /dev/null @@ -1,33 +0,0 @@ -.deleteBtn { - background: none; - border: none; - cursor: pointer; - font-size: 18px; - color: #444; - height: 100; -} - -.deleteBtn:hover { - color: var(--Brand-Green-Green, #3A8088); -} - -.deleteBtn.disabled { - cursor: not-allowed; - opacity: 0.5; - background: none; - border: none; - cursor: pointer; - font-size: 18px; - color: #444; -} - -.deleteBtn.disabled:hover { - color: #444; -} - -.deleteBtnContainer { - display: flex; - align-items: center; - justify-content: center; - -} diff --git a/src/components/Mitglieder/MitgliederItemDelete/MitgliederItemDelete.tsx b/src/components/Mitglieder/MitgliederItemDelete/MitgliederItemDelete.tsx deleted file mode 100644 index 4bb686f..0000000 --- a/src/components/Mitglieder/MitgliederItemDelete/MitgliederItemDelete.tsx +++ /dev/null @@ -1,37 +0,0 @@ -import { FaTrash } from "react-icons/fa"; -import styles from "./MitgliederItemDelete.module.css"; -import { useState } from "react"; -import DeletePopUp from "./DeletePopUp"; -import { User } from "../../../hooks/useUsers"; - -type MitgliederItemDeleteProps = { - user: User; - refetchUsers: () => Promise; - isDisabled?: boolean; -}; - -const MitgliederItemDelete = ({ user, refetchUsers, isDisabled = false }: MitgliederItemDeleteProps) => { - const [deleteWindow, setDeleteWindow] = useState(false); - - return ( -
    - - - {deleteWindow && ( - setDeleteWindow(false)} - refetchUsers={refetchUsers} - /> - )} -
    - ); - }; - - export default MitgliederItemDelete; \ No newline at end of file diff --git a/src/components/Mitglieder/MitgliederItemEdit/EditPopUp.module.css b/src/components/Mitglieder/MitgliederItemEdit/EditPopUp.module.css deleted file mode 100644 index 0faf35d..0000000 --- a/src/components/Mitglieder/MitgliederItemEdit/EditPopUp.module.css +++ /dev/null @@ -1,89 +0,0 @@ -.popupHeader { - display: flex; - justify-content: space-between; - align-items: center; - padding: 15px 20px; -} - -.popupHeader p { - font-size: 1.2rem; - font-weight: 600; - margin: 0; -} - -.closeButton { - background: none; - border: none; - cursor: pointer; - display: flex; - align-items: center; - justify-content: center; -} - -.closeIcon { - font-size: 1.5rem; - color: #666; -} - -.horizontalLineLight { - height: 1px; - background-color: #e0e0e0; - width: 100%; - margin: 0; -} - -.form { - box-sizing: border-box; - max-width: 100%; - padding: 20px; -} - -.formGroup { - margin-bottom: 15px; - box-sizing: border-box; -} - -.formGroup label { - display: block; - margin-bottom: 5px; - font-weight: 500; -} - -.formGroup input, -.formGroup select { - width: 100%; - padding: 8px 12px; - border: 1px solid #ddd; - border-radius: 4px; - font-size: 1rem; - box-sizing: border-box; -} - -.submitButtonDiv { - display: flex; - justify-content: flex-end; - padding: 15px 0 10px; -} - -.submitButton { - background-color: #4c9aff; - color: white; - border: none; - border-radius: 4px; - padding: 8px 16px; - font-size: 1rem; - cursor: pointer; - transition: background-color 0.2s; -} - -.submitButton:hover { - background-color: #3d8df5; -} - -.userInfo h2 { - margin-top: 0; - margin-bottom: 10px; -} - - - diff --git a/src/components/Mitglieder/MitgliederItemEdit/EditPopUp.tsx b/src/components/Mitglieder/MitgliederItemEdit/EditPopUp.tsx deleted file mode 100644 index 2041f95..0000000 --- a/src/components/Mitglieder/MitgliederItemEdit/EditPopUp.tsx +++ /dev/null @@ -1,152 +0,0 @@ -import { IoCloseOutline } from "react-icons/io5"; -import { useState } from "react"; -import styles from "./EditPopUp.module.css"; -import { User, useOrgUsers } from "../../../hooks/useUsers"; - -type EditPopUpProps = { - closePopup: () => void; - refetchUsers: () => Promise; - user: User; -}; - -const EditPopUp = ({ closePopup, refetchUsers, user }: EditPopUpProps) => { - const { updateUser } = useOrgUsers(); - const [formData, setFormData] = useState({ - fullName: user.fullName || "", - email: user.email || "", - privilege: user.privilege || "", - username: user.username || "" - }); - const [isSubmitting, setIsSubmitting] = useState(false); - const [error, setError] = useState(null); - - const handleChange = (e: React.ChangeEvent) => { - const { name, value } = e.target; - setFormData(prev => ({ - ...prev, - [name]: value - })); - }; - - const handleSubmit = async (e: React.FormEvent) => { - e.preventDefault(); - setIsSubmitting(true); - setError(null); - - try { - await updateUser(user.id, { - fullName: formData.fullName, - email: formData.email, - privilege: formData.privilege, - username: formData.username - }); - - // Refresh the users list and close the popup - await refetchUsers(); - closePopup(); - } catch (error: any) { - setError(error.message || "Failed to update user"); - } finally { - setIsSubmitting(false); - } - }; - - return ( -
    -
    -
    -

    Edit User

    - -
    -
    - {error &&
    {error}
    } -
    -
    - - -
    -
    - - -
    -
    - - -
    -
    - - -
    -
    -
    - -
    -
    -
    -
    - ); -}; - -const popupStyles: { overlay: React.CSSProperties; popup: React.CSSProperties } = { - overlay: { - position: "fixed", - top: 0, - left: 0, - right: 0, - bottom: 0, - backgroundColor: "rgba(0,0,0,0.5)", - display: "flex", - justifyContent: "center", - alignItems: "center", - - }, - popup: { - backgroundColor: "#fff", - borderRadius: "8px", - boxShadow: "0 5px 15px rgba(0,0,0,0.3)", - position: "relative", - width: "400px", - maxWidth: "90%" - } -}; - -export default EditPopUp; \ No newline at end of file diff --git a/src/components/Mitglieder/MitgliederItemEdit/MitgliederItemEdit.module.css b/src/components/Mitglieder/MitgliederItemEdit/MitgliederItemEdit.module.css deleted file mode 100644 index 7c91679..0000000 --- a/src/components/Mitglieder/MitgliederItemEdit/MitgliederItemEdit.module.css +++ /dev/null @@ -1,12 +0,0 @@ -.editBtn { - background: none; - border: none; - cursor: pointer; - font-size: 18px; - color: #444; - height: 100; -} - -.editBtn:hover { - color: #3d8df5; -} \ No newline at end of file diff --git a/src/components/Mitglieder/MitgliederItemEdit/MitgliederItemEdit.tsx b/src/components/Mitglieder/MitgliederItemEdit/MitgliederItemEdit.tsx deleted file mode 100644 index aa21877..0000000 --- a/src/components/Mitglieder/MitgliederItemEdit/MitgliederItemEdit.tsx +++ /dev/null @@ -1,36 +0,0 @@ -import { FaEdit } from "react-icons/fa"; -import { useState } from "react"; -import styles from "./MitgliederItemEdit.module.css"; -import EditPopUp from "./EditPopUp"; -import { User } from "../../../hooks/useUsers"; - -type MitgliederItemEditProps = { - user: User; - refetchUsers: () => Promise; -}; - -const MitgliederItemEdit = ({ user, refetchUsers }: MitgliederItemEditProps) => { - const [editWindow, setEditWindow] = useState(false); - - return ( -
    - - - {editWindow && ( - setEditWindow(false)} - refetchUsers={refetchUsers} - /> - )} -
    - ); -}; - -export default MitgliederItemEdit; \ No newline at end of file diff --git a/src/components/Mitglieder/MitgliederTable.module.css b/src/components/Mitglieder/MitgliederTable.module.css new file mode 100644 index 0000000..cf676b0 --- /dev/null +++ b/src/components/Mitglieder/MitgliederTable.module.css @@ -0,0 +1,64 @@ +/* Main table container */ +.mitgliederTable { + width: 100%; + height: 100%; + display: flex; + flex-direction: column; + gap: 20px; +} + +/* FormGenerator container */ +.mitgliederFormGenerator { + flex: 1; + min-height: 0; +} + +/* Error state styling */ +.errorState { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + padding: 40px; + gap: 20px; + color: var(--color-text); + font-family: var(--font-family); + text-align: center; +} + +.retryButton { + padding: 10px 20px; + border: 1px solid var(--color-primary); + border-radius: 20px; + background: var(--color-bg); + color: var(--color-text); + cursor: pointer; + transition: all 0.2s ease; + font-family: var(--font-family); +} + +.retryButton:hover { + background: var(--color-primary); + color: var(--color-bg); +} + +/* User-specific formatting */ +.userName { + font-weight: 500; + color: var(--color-text); +} + +.userFullName { + color: var(--color-text); +} + +.userEmail { + color: var(--color-gray); + font-size: 0.9em; +} + +.userLanguage { + color: var(--color-text); + font-size: 0.85em; +} + \ No newline at end of file diff --git a/src/components/Mitglieder/MitgliederTable.tsx b/src/components/Mitglieder/MitgliederTable.tsx new file mode 100644 index 0000000..9b3d7fa --- /dev/null +++ b/src/components/Mitglieder/MitgliederTable.tsx @@ -0,0 +1,50 @@ +import { FormGenerator } from '../FormGenerator/FormGenerator'; +import { useMitgliederLogic } from './mitgliederLogic'; +import { MitgliederTableProps } from './mitgliederTypes'; +import { useLanguage } from '../../contexts/LanguageContext'; +import styles from './MitgliederTable.module.css'; + +function MitgliederTable({ className = '' }: MitgliederTableProps) { + const { t } = useLanguage(); + const { + users, + loading, + error, + columns, + actions, + refetch + } = useMitgliederLogic(); + + if (error) { + return ( +
    +

    {t('users.error.loading', 'Error loading users:')} {error}

    + +
    + ); + } + + return ( +
    + +
    + ); +} + +export default MitgliederTable; \ No newline at end of file diff --git a/src/components/Mitglieder/index.ts b/src/components/Mitglieder/index.ts new file mode 100644 index 0000000..82b1d4f --- /dev/null +++ b/src/components/Mitglieder/index.ts @@ -0,0 +1,3 @@ +export { default as MitgliederTable } from './MitgliederTable'; +export { useMitgliederLogic } from './mitgliederLogic'; +export type * from './mitgliederTypes'; diff --git a/src/components/Mitglieder/mitgliederLogic.tsx b/src/components/Mitglieder/mitgliederLogic.tsx new file mode 100644 index 0000000..e188a73 --- /dev/null +++ b/src/components/Mitglieder/mitgliederLogic.tsx @@ -0,0 +1,107 @@ +import React, { useMemo } from 'react'; + +import { useOrgUsers, User } from '../../hooks/useUsers'; +import { useLanguage } from '../../contexts/LanguageContext'; + +import type { + MitgliederLogicReturn, + UserActionConfig, + UserColumnConfig +} from './mitgliederTypes'; + +export function useMitgliederLogic(): MitgliederLogicReturn { + const { users, loading, error, refetch, deleteUser } = useOrgUsers(); + const { t } = useLanguage(); + + // Configure columns for the users table + const columns: UserColumnConfig[] = useMemo(() => [ + { + key: 'username', + label: t('users.column.username', 'Username'), + type: 'string', + width: 150, + minWidth: 120, + maxWidth: 200, + sortable: true, + filterable: true, + searchable: true, + formatter: (value: string | undefined) => ( + + {value || t('users.noUsername', 'No Username')} + + ) + }, + { + key: 'fullName', + label: t('users.column.name', 'Name'), + type: 'string', + width: 200, + minWidth: 150, + maxWidth: 300, + sortable: true, + filterable: true, + searchable: true, + formatter: (value: string | undefined) => ( + + {value || t('users.noName', 'No Name')} + + ) + }, + { + key: 'email', + label: t('users.column.email', 'Email'), + type: 'string', + width: 250, + minWidth: 200, + maxWidth: 350, + sortable: true, + filterable: true, + searchable: true, + formatter: (value: string | undefined) => ( + + {value || t('users.noEmail', 'No Email')} + + ) + }, + { + key: 'language', + label: t('users.column.language', 'Language'), + type: 'enum', + width: 120, + minWidth: 100, + maxWidth: 150, + sortable: true, + filterable: true, + filterOptions: ['en', 'de', 'fr'], + formatter: (value: string | undefined) => { + const languageMap: Record = { + 'en': t('language.english', 'English'), + 'de': t('language.german', 'Deutsch'), + 'fr': t('language.french', 'Français') + }; + return ( + + {value ? languageMap[value] || value : t('users.noLanguage', 'No Language')} + + ); + } + } + ], [t]); + + // Configure action buttons (empty for now) + const actions: UserActionConfig[] = useMemo(() => [], []); + + return { + // Data + users, + loading, + error, + + // Refetch function + refetch, + + // Additional data for rendering + columns, + actions + }; +} diff --git a/src/components/Mitglieder/mitgliederTypes.ts b/src/components/Mitglieder/mitgliederTypes.ts new file mode 100644 index 0000000..4e8c4f2 --- /dev/null +++ b/src/components/Mitglieder/mitgliederTypes.ts @@ -0,0 +1,44 @@ +import React from 'react'; +import { User } from '../../hooks/useUsers'; + +// Props for the MitgliederTable component +export interface MitgliederTableProps { + className?: string; +} + +// Action configuration for user actions +export interface UserActionConfig { + label: string; + icon: (row: User) => React.ReactElement; + onClick: (row: User) => void; +} + +// Column configuration for the users table +export interface UserColumnConfig { + key: string; + label: string; + type: 'string' | 'number' | 'date' | 'boolean' | 'enum'; + width: number; + minWidth: number; + maxWidth: number; + sortable: boolean; + filterable: boolean; + searchable?: boolean; + filterOptions?: string[]; + formatter: (value: any, row?: any) => React.ReactElement | string; +} + +// Return type for the mitglieder logic hook +export interface MitgliederLogicReturn { + // Data + users: User[]; + loading: boolean; + error: string | null; + + // Refetch function + refetch: () => Promise; + + // Additional data for rendering + columns: UserColumnConfig[]; + actions: UserActionConfig[]; +} diff --git a/src/components/PageManager/pageConfigs.ts b/src/components/PageManager/pageConfigs.ts index d59441e..13930c3 100644 --- a/src/components/PageManager/pageConfigs.ts +++ b/src/components/PageManager/pageConfigs.ts @@ -6,6 +6,7 @@ import { MdOutlineWorkOutline } from 'react-icons/md'; import { LuWorkflow, LuTicket } from "react-icons/lu"; import { GoGear } from "react-icons/go"; import { FaPlug, FaRegFileAlt, FaShare } from "react-icons/fa"; +import { LuMessageSquareText } from "react-icons/lu"; // Lazy load components for better performance const Dashboard = lazy(() => import('../../pages/Home/Dashboard')); @@ -15,6 +16,7 @@ const Connections = lazy(() => import('../../pages/Home/Connections')); const Workflows = lazy(() => import('../../pages/Home/Workflows')); const Einstellungen = lazy(() => import('../../pages/Home/Einstellungen')); const TestSharepoint = lazy(() => import('../../pages/Home/TestSharepoint')); +const Prompts = lazy(() => import('../../pages/Home/Prompts')); // Page configuration with caching and lifecycle settings export const pageConfigs: PageConfig[] = [ @@ -61,6 +63,28 @@ export const pageConfigs: PageConfig[] = [ if (import.meta.env.DEV) console.log('Dateien unloaded - cleanup file references'); } }, + { + path: 'prompts', + component: Prompts, + persistent: false, + preload: true, + moduleEnabled: true, + // Sidebar properties + id: '4', + name: 'Prompts', + icon: LuMessageSquareText , + order: 3, + showInSidebar: true, + onActivate: async () => { + if (import.meta.env.DEV) console.log('Prompts activated'); + }, + onLoad: async () => { + if (import.meta.env.DEV) console.log('Prompts loaded - can initialize prompts here'); + }, + onUnload: async () => { + if (import.meta.env.DEV) console.log('Prompts unloaded - cleanup prompts references'); + } + }, { path: 'team-bereich', component: TeamBereich, @@ -103,7 +127,7 @@ export const pageConfigs: PageConfig[] = [ preload: true, // Preload workflows for better performance moduleEnabled: true, // Sidebar properties - id: '4', + id: '6', name: 'Workflows', icon: LuWorkflow, order: 3, diff --git a/src/components/Popup/EditForm.module.css b/src/components/Popup/EditForm.module.css index 05e8290..1f3f3c4 100644 --- a/src/components/Popup/EditForm.module.css +++ b/src/components/Popup/EditForm.module.css @@ -44,6 +44,35 @@ box-shadow: 0 0 0 3px rgba(239, 68, 68, 0.1); } +/* Textarea styling */ +.fieldTextarea { + 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; +} + +.fieldTextarea:focus { + outline: none; + border-color: var(--color-secondary); +} + +.fieldTextarea.fieldError { + border-color: #ef4444; + box-shadow: 0 0 0 3px rgba(239, 68, 68, 0.1); +} + /* Floating label styles */ .label { position: absolute; diff --git a/src/components/Popup/EditForm.tsx b/src/components/Popup/EditForm.tsx index 25d8a39..22974fb 100644 --- a/src/components/Popup/EditForm.tsx +++ b/src/components/Popup/EditForm.tsx @@ -5,13 +5,15 @@ import styles from './EditForm.module.css'; export interface EditFieldConfig { key: string; label: string; - type: 'string' | 'email' | 'date' | 'enum' | 'boolean' | 'readonly'; + type: 'string' | 'email' | 'date' | 'enum' | 'boolean' | 'readonly' | 'textarea'; editable: boolean; required?: boolean; options?: string[]; // For enum types formatter?: (value: any) => string; // For display formatting validator?: (value: any) => string | null; // Returns error message or null placeholder?: string; + minRows?: number; // For textarea types + maxRows?: number; // For textarea types } // EditForm props @@ -46,7 +48,29 @@ export function EditForm>({ setEditedData({ ...data }); setErrors({}); setFieldFocused({}); - }, [data]); + + // Initialize textarea heights for textarea fields + setTimeout(() => { + fields.forEach(field => { + if (field.type === 'textarea') { + const textarea = document.querySelector(`textarea[name="${field.key}"]`) as HTMLTextAreaElement; + if (textarea) { + const minRows = field.minRows || 4; + const maxRows = field.maxRows || 8; + textarea.style.height = 'auto'; + const newHeight = Math.max( + minRows * 1.5 * 16, + Math.min( + textarea.scrollHeight, + maxRows * 1.5 * 16 + ) + ); + textarea.style.height = `${newHeight}px`; + } + } + }); + }, 0); + }, [data, fields]); // Handle field focus const handleFieldFocus = (fieldKey: string, focused: boolean) => { @@ -194,6 +218,44 @@ export function EditForm>({ ); } + // Handle textarea type + if (field.type === 'textarea') { + const minRows = field.minRows || 4; + const maxRows = field.maxRows || 8; + + return ( +
    +