Add contact management functionality with CRUD operations and UI enhancements

This commit is contained in:
2025-11-15 13:36:38 +07:00
parent 7dd38aa50c
commit 8cf5878d46
4 changed files with 204 additions and 171 deletions

View File

@@ -1,7 +1,8 @@
import React, { memo, useEffect, useState } from 'react';
import { Modal, Input, Button, Switch, ConfigProvider, Typography, Divider } from 'antd';
import { Modal, Input, Button, Switch, ConfigProvider, Typography, Divider, Select } from 'antd';
import { NotifAlert, NotifOk } from '../../../components/Global/ToastNotif';
import { validateRun } from '../../../Utils/validate';
import { createContact, updateContact } from '../../../api/contact';
const { Text } = Typography;
@@ -13,6 +14,7 @@ const DetailContact = memo(function DetailContact(props) {
name: '',
phone: '',
is_active: true,
contact_type: 'operator',
};
const [formData, setFormData] = useState(defaultData);
@@ -26,6 +28,10 @@ const DetailContact = memo(function DetailContact(props) {
} else if (e && e.type === 'change') {
name = e.name || e.target?.name;
value = e.value !== undefined ? e.value : e.checked;
} else if (typeof e === 'string' || typeof e === 'number') {
// Handle Select onChange
value = e;
name = 'contact_type';
} else {
return;
}
@@ -53,12 +59,13 @@ const DetailContact = memo(function DetailContact(props) {
const handleSave = async () => {
setConfirmLoading(true);
// Custom validation untuk phone
if (formData.phone && !/^[\d\s\+\-\(\)]+$/.test(formData.phone)) {
// Custom validation untuk phone - Indonesian phone format
const phoneRegex = /^(?:\+62|0)8\d{7,10}$/;
if (formData.phone && !phoneRegex.test(formData.phone.replace(/[\s\-\(\)]/g, ''))) {
NotifOk({
icon: 'warning',
title: 'Peringatan',
message: 'Nomor telepon hanya boleh mengandung angka, spasi, +, -, dan ()',
message: 'Nomor telepon harus format Indonesia (+628XXXXXXXXX atau 08XXXXXXXXX)',
});
setConfirmLoading(false);
return;
@@ -68,6 +75,7 @@ const DetailContact = memo(function DetailContact(props) {
const validationRules = [
{ field: 'name', label: 'Contact Name', required: true },
{ field: 'phone', label: 'Phone', required: true },
{ field: 'contact_type', label: 'Contact Type', required: true },
];
if (
@@ -80,15 +88,18 @@ const DetailContact = memo(function DetailContact(props) {
try {
const contactData = {
id: props.selectedData?.id || null,
name: formData.name,
phone: formData.phone,
contact_name: formData.name,
contact_phone: formData.phone.replace(/[\s\-\(\)]/g, ''), // Clean phone number
is_active: formData.is_active,
status: formData.is_active ? 'active' : 'inactive',
contact_type: formData.contact_type,
};
console.log('Saving contact data:', contactData);
await new Promise((resolve) => setTimeout(resolve, 1000));
let response;
if (props.actionMode === 'edit') {
response = await updateContact(props.selectedData.contact_id || props.selectedData.id, contactData);
} else {
response = await createContact(contactData);
}
NotifAlert({
icon: 'success',
@@ -98,14 +109,14 @@ const DetailContact = memo(function DetailContact(props) {
}.`,
});
props.onContactSaved?.(contactData, props.actionMode);
props.onContactSaved?.(response.data, props.actionMode);
handleCancel();
} catch (error) {
console.error('Save failed:', error);
NotifAlert({
icon: 'error',
title: 'Error',
message: 'Terjadi kesalahan saat menyimpan data.',
message: error.response?.data?.message || 'Terjadi kesalahan saat menyimpan data.',
});
} finally {
setConfirmLoading(false);
@@ -121,19 +132,21 @@ const DetailContact = memo(function DetailContact(props) {
if (props.showModal) {
if (props.actionMode === 'edit' && props.selectedData) {
setFormData({
name: props.selectedData.name,
phone: props.selectedData.phone,
is_active: props.selectedData.status === 'active',
name: props.selectedData.contact_name || props.selectedData.name,
phone: props.selectedData.contact_phone || props.selectedData.phone,
is_active: props.selectedData.is_active || props.selectedData.status === 'active',
contact_type: props.selectedData.contact_type || props.contactType || 'operator',
});
} else if (props.actionMode === 'add') {
setFormData({
name: '',
phone: '',
is_active: true,
contact_type: props.contactType === 'all' ? 'operator' : props.contactType || 'operator',
});
}
}
}, [props.showModal, props.actionMode, props.selectedData]);
}, [props.showModal, props.actionMode, props.selectedData, props.contactType]);
return (
<Modal
@@ -228,6 +241,20 @@ const DetailContact = memo(function DetailContact(props) {
style={{ color: formData.is_active ? '#000000' : '#ff4d4f' }}
/>
</div>
<div style={{ marginBottom: 12 }}>
<Text strong>Contact Type</Text>
<Text style={{ color: 'red' }}> *</Text>
<Select
value={formData.contact_type}
onChange={handleInputChange}
placeholder="Select Contact Type"
disabled={props.readOnly}
style={{ width: '100%' }}
>
<Select.Option value="operator">Operator</Select.Option>
<Select.Option value="gudang">Gudang</Select.Option>
</Select>
</div>
</div>
</Modal>
);