Shyamnath's picture
Push UI dashboard and deployment files
c40c75a
import React, { useState, useEffect } from 'react';
import { Modal, Form, Input, Select as AntSelect, Button as AntButton, message } from 'antd';
import { Select, SelectItem } from "@tremor/react";
import { Card, Text } from "@tremor/react";
interface BaseMember {
user_email?: string;
user_id?: string;
role: string;
}
interface ModalConfig {
title: string;
roleOptions: Array<{
label: string;
value: string;
}>;
defaultRole?: string;
showEmail?: boolean;
showUserId?: boolean;
additionalFields?: Array<{
name: string;
label: string;
type: 'input' | 'select';
options?: Array<{ label: string; value: string }>;
rules?: any[];
}>;
}
interface MemberModalProps<T extends BaseMember> {
visible: boolean;
onCancel: () => void;
onSubmit: (data: T) => void;
initialData?: T | null;
mode: 'add' | 'edit';
config: ModalConfig;
}
const MemberModal = <T extends BaseMember>({
visible,
onCancel,
onSubmit,
initialData,
mode,
config
}: MemberModalProps<T>) => {
const [form] = Form.useForm();
console.log("Initial Data:", initialData);
// Reset form and set initial values when modal becomes visible or initialData changes
useEffect(() => {
if (visible) {
if (mode === 'edit' && initialData) {
// For edit mode, use the initialData values
form.setFieldsValue({
...initialData,
// Ensure role is set correctly for editing
role: initialData.role || config.defaultRole
});
} else {
// For add mode, reset to defaults
form.resetFields();
form.setFieldsValue({
role: config.defaultRole || config.roleOptions[0]?.value
});
}
}
}, [visible, initialData, mode, form, config.defaultRole, config.roleOptions]);
const handleSubmit = async (values: any) => {
try {
// Trim string values
const formData = Object.entries(values).reduce((acc, [key, value]) => ({
...acc,
[key]: typeof value === 'string' ? value.trim() : value
}), {}) as T;
onSubmit(formData);
form.resetFields();
message.success(`Successfully ${mode === 'add' ? 'added' : 'updated'} member`);
} catch (error) {
message.error('Failed to submit form');
console.error('Form submission error:', error);
}
};
// Helper function to get role label from value
const getRoleLabel = (value: string) => {
return config.roleOptions.find(option => option.value === value)?.label || value;
};
const renderField = (field: {
name: string;
label: string;
type: 'input' | 'select';
options?: Array<{ label: string; value: string }>;
rules?: any[];
}) => {
switch (field.type) {
case 'input':
return (
<Input
className="px-3 py-2 border rounded-md w-full"
onChange={(e) => {
e.target.value = e.target.value.trim();
}}
/>
);
case 'select':
return (
<AntSelect>
{field.options?.map(option => (
<AntSelect.Option key={option.value} value={option.value}>
{option.label}
</AntSelect.Option>
))}
</AntSelect>
);
default:
return null;
}
};
return (
<Modal
title={config.title || (mode === 'add' ? "Add Member" : "Edit Member")}
open={visible}
width={800}
footer={null}
onCancel={onCancel}
>
<Form
form={form}
onFinish={handleSubmit}
labelCol={{ span: 8 }}
wrapperCol={{ span: 16 }}
labelAlign="left"
>
{config.showEmail && (
<Form.Item
label="Email"
name="user_email"
className="mb-4"
rules={[
{ type: 'email', message: 'Please enter a valid email!' }
]}
>
<Input
className="px-3 py-2 border rounded-md w-full"
placeholder="[email protected]"
onChange={(e) => {
e.target.value = e.target.value.trim();
}}
/>
</Form.Item>
)}
{config.showEmail && config.showUserId && (
<div className="text-center mb-4">
<Text>OR</Text>
</div>
)}
{config.showUserId && (
<Form.Item
label="User ID"
name="user_id"
className="mb-4"
>
<Input
className="px-3 py-2 border rounded-md w-full"
placeholder="user_123"
onChange={(e) => {
e.target.value = e.target.value.trim();
}}
/>
</Form.Item>
)}
<Form.Item
label={
<div className="flex items-center gap-2">
<span>Role</span>
{mode === 'edit' && initialData && (
<span className="text-gray-500 text-sm">
(Current: {getRoleLabel(initialData.role)})
</span>
)}
</div>
}
name="role"
className="mb-4"
rules={[
{ required: true, message: 'Please select a role!' }
]}
>
<AntSelect>
{mode === 'edit' && initialData
? [
// Current role first
...config.roleOptions.filter(option => option.value === initialData.role),
// Then all other roles
...config.roleOptions.filter(option => option.value !== initialData.role)
].map(option => (
<AntSelect.Option key={option.value} value={option.value}>
{option.label}
</AntSelect.Option>
))
: config.roleOptions.map(option => (
<AntSelect.Option key={option.value} value={option.value}>
{option.label}
</AntSelect.Option>
))}
</AntSelect>
</Form.Item>
{config.additionalFields?.map(field => (
<Form.Item
key={field.name}
label={field.label}
name={field.name}
className="mb-4"
rules={field.rules}
>
{renderField(field)}
</Form.Item>
))}
<div className="text-right mt-6">
<AntButton
onClick={onCancel}
className="mr-2"
>
Cancel
</AntButton>
<AntButton
type="default"
htmlType="submit"
>
{mode === 'add' ? 'Add Member' : 'Save Changes'}
</AntButton>
</div>
</Form>
</Modal>
);
};
export default MemberModal;