This commit is contained in:
chamikaJ
2025-04-17 18:28:54 +05:30
parent f583291d8a
commit 8825b0410a
2837 changed files with 241385 additions and 127578 deletions

View File

@@ -0,0 +1,60 @@
import { Table, TableProps, Typography } from 'antd';
import React, { useMemo } from 'react';
import { IOrganizationAdmin } from '@/types/admin-center/admin-center.types';
interface OrganizationAdminsTableProps {
organizationAdmins: IOrganizationAdmin[] | null;
loading: boolean;
themeMode: string;
}
const { Text } = Typography;
const OrganizationAdminsTable: React.FC<OrganizationAdminsTableProps> = ({
organizationAdmins,
loading,
themeMode,
}) => {
const columns = useMemo<TableProps<IOrganizationAdmin>['columns']>(
() => [
{
title: <Text strong>Name</Text>,
dataIndex: 'name',
key: 'name',
render: (text, record) => (
<div>
<Text>
{text}
{record.is_owner && <Text> (Owner)</Text>}
</Text>
</div>
),
},
{
title: <Text strong>Email</Text>,
dataIndex: 'email',
key: 'email',
render: text => <Text>{text}</Text>,
},
],
[]
);
return (
<Table<IOrganizationAdmin>
className="organization-admins-table"
columns={columns}
dataSource={organizationAdmins || []}
loading={loading}
showHeader={false}
pagination={{
size: 'small',
pageSize: 10,
hideOnSinglePage: true,
}}
rowKey="email"
/>
);
};
export default OrganizationAdminsTable;

View File

@@ -0,0 +1,122 @@
import { adminCenterApiService } from '@/api/admin-center/admin-center.api.service';
import logger from '@/utils/errorLogger';
import { EnterOutlined, EditOutlined } from '@ant-design/icons';
import { Card, Button, Tooltip, Typography } from 'antd';
import TextArea from 'antd/es/input/TextArea';
import Paragraph from 'antd/es/typography/Paragraph';
import { TFunction } from 'i18next';
import { useState, useEffect } from 'react';
interface OrganizationNameProps {
themeMode: string;
name: string;
t: TFunction;
refetch: () => void;
}
const OrganizationName = ({ themeMode, name, t, refetch }: OrganizationNameProps) => {
const [isEditable, setIsEditable] = useState(false);
const [newName, setNewName] = useState(name);
useEffect(() => {
setNewName(name);
}, [name]);
const handleBlur = () => {
if (newName.trim() === '') {
setNewName(name);
setIsEditable(false);
return;
}
if (newName !== name) {
updateOrganizationName();
}
setIsEditable(false);
};
const handleNameChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {
setNewName(e.target.value);
};
const updateOrganizationName = async () => {
try {
const trimmedName = newName.trim();
const res = await adminCenterApiService.updateOrganizationName({ name: trimmedName });
if (res.done) {
refetch();
}
} catch (error) {
logger.error('Error updating organization name', error);
setNewName(name);
}
};
const handleKeyDown = (e: React.KeyboardEvent) => {
if (e.key === 'Escape') {
setNewName(name);
setIsEditable(false);
}
};
return (
<Card>
<Typography.Title level={5} style={{ margin: 0, marginBottom: '0.5rem' }}>
{t('name')}
</Typography.Title>
<div style={{ paddingTop: '8px' }}>
<div style={{ marginBottom: '8px' }}>
{isEditable ? (
<div style={{ position: 'relative' }}>
<TextArea
style={{
height: '32px',
paddingRight: '40px',
resize: 'none',
borderRadius: '4px',
}}
onPressEnter={handleBlur}
value={newName}
onChange={handleNameChange}
onBlur={handleBlur}
onKeyDown={handleKeyDown}
autoFocus
maxLength={100}
placeholder={t('enterOrganizationName')}
/>
<Button
icon={<EnterOutlined style={{ color: '#1890ff' }} />}
type="text"
style={{
position: 'absolute',
right: '4px',
top: '50%',
transform: 'translateY(-50%)',
padding: '4px 8px',
color: '#1890ff',
}}
onClick={handleBlur}
/>
</div>
) : (
<Typography.Text>
<div style={{ display: 'flex', alignItems: 'center', gap: '8px' }}>
{name}
<Tooltip title={t('edit')}>
<Button
onClick={() => setIsEditable(true)}
size="small"
type="text"
icon={<EditOutlined />}
style={{ padding: '4px', color: '#1890ff' }}
/>
</Tooltip>
</div>
</Typography.Text>
)}
</div>
</div>
</Card>
);
};
export default OrganizationName;

View File

@@ -0,0 +1,120 @@
import { adminCenterApiService } from '@/api/admin-center/admin-center.api.service';
import { IOrganization } from '@/types/admin-center/admin-center.types';
import logger from '@/utils/errorLogger';
import { MailOutlined, PhoneOutlined, EditOutlined } from '@ant-design/icons';
import { Card, Tooltip, Input, Button, Typography, InputRef } from 'antd';
import { TFunction } from 'i18next';
import { useEffect, useRef, useState } from 'react';
interface OrganizationOwnerProps {
themeMode: string;
organization: IOrganization | null;
t: TFunction;
refetch: () => void;
}
const OrganizationOwner = ({ themeMode, organization, t, refetch }: OrganizationOwnerProps) => {
const [isEditableContactNumber, setIsEditableContactNumber] = useState(false);
const [number, setNumber] = useState(organization?.contact_number || '');
const contactNoRef = useRef<InputRef>(null);
const handleContactNumberBlur = () => {
setIsEditableContactNumber(false);
updateOrganizationContactNumber();
};
const updateOrganizationContactNumber = async () => {
try {
const res = await adminCenterApiService.updateOwnerContactNumber({ contact_number: number });
if (res.done) {
refetch();
}
} catch (error) {
logger.error('Error updating organization contact number:', error);
}
};
const addContactNumber = () => {
setIsEditableContactNumber(true);
setTimeout(() => {
contactNoRef.current?.focus();
}, 500);
};
const handleEditContactNumber = () => {
setIsEditableContactNumber(true);
};
const handleContactNumber = (e: React.ChangeEvent<HTMLInputElement>) => {
const inputValue = e.target.value;
setNumber(inputValue);
};
return (
<Card>
<Typography.Title level={5} style={{ margin: 0, marginBottom: '0.5rem' }}>
{t('owner')}
</Typography.Title>
<div style={{ paddingTop: '8px' }}>
<div style={{ marginBottom: '8px' }}>
<Typography.Text
style={{
color: `${themeMode === 'dark' ? '#ffffffd9' : '#000000d9'}`,
}}
>
{organization?.owner_name || ''}
</Typography.Text>
</div>
</div>
<Typography.Paragraph style={{ display: 'flex', alignItems: 'center', margin: 0 }}>
<Typography.Text
style={{
color: `${themeMode === 'dark' ? '#ffffffd9' : '#000000d9'}`,
}}
>
<span style={{ marginRight: '8px' }}>
<Tooltip title="Email Address">
<MailOutlined />
</Tooltip>
</span>
{organization?.email || ''}
</Typography.Text>
</Typography.Paragraph>
<Typography.Paragraph style={{ marginTop: '0.5rem', marginBottom: 0 }}>
<Tooltip title="Contact Number">
<span style={{ marginRight: '8px' }}>
<PhoneOutlined />
</span>
</Tooltip>
{isEditableContactNumber ? (
<Input
onChange={handleContactNumber}
onPressEnter={handleContactNumberBlur}
onBlur={handleContactNumberBlur}
style={{ width: '200px' }}
value={number}
type="text"
maxLength={15}
ref={contactNoRef}
/>
) : number === '' ? (
<Typography.Link onClick={addContactNumber}>{t('contactNumber')}</Typography.Link>
) : (
<Typography.Text>
{number}
<Tooltip title="Edit">
<Button
onClick={handleEditContactNumber}
size="small"
type="link"
icon={<EditOutlined />}
/>
</Tooltip>
</Typography.Text>
)}
</Typography.Paragraph>
</Card>
);
};
export default OrganizationOwner;