This commit is contained in:
Raja Oktafrianto
2025-04-23 13:40:01 +07:00
34 changed files with 933 additions and 511 deletions

View File

@ -10,48 +10,63 @@ const HeaderTopbar = () => {
const itemChatRef = useRef<any>(null); const itemChatRef = useRef<any>(null);
const itemUserRef = useRef<any>(null); const itemUserRef = useRef<any>(null);
const itemNotificationsRef = useRef<any>(null); const itemNotificationsRef = useRef<any>(null);
const { isRTL } = useLanguage(); const { isRTL } = useLanguage();
const [isSticky, setIsSticky] = useState(false);
useEffect(() => {
const handleScroll = () => {
setIsSticky(window.scrollY > 100);
};
window.addEventListener('scroll', handleScroll);
return () => window.removeEventListener('scroll', handleScroll);
}, []);
const handleDropdownChatShow = () => { const handleDropdownChatShow = () => {
window.dispatchEvent(new Event('resize')); window.dispatchEvent(new Event('resize'));
}; };
// console.log(getAuth())
return ( return (
<div className="flex items-center gap-4"> <div className="flex items-center gap-4">
<div className="hidden md:flex flex-col items-end mr-2 text-right"> <div className="hidden md:flex flex-col items-end mr-2 text-right">
<span className="font-semibold text-sm text-white leading-tight">{getAuth()?.user.username}</span> <span
<span className="text-xs text-gray-400">{getAuth()?.role_name}</span> className={`font-semibold text-sm leading-tight ${isSticky ? 'text-black' : 'text-white'}`}
</div> >
{getAuth()?.user.username}
<Menu> </span>
<MenuItem <span className={`text-xs ${isSticky ? 'text-gray-700' : 'text-gray-400'}`}>
ref={itemUserRef} {getAuth()?.role_name}
toggle="dropdown" </span>
trigger="click" </div>
dropdownProps={{
placement: isRTL() ? 'bottom-start' : 'bottom-end',
modifiers: [
{
name: 'offset',
options: {
offset: [20, 10],
},
},
],
}}
>
<MenuToggle className="btn btn-icon rounded-full">
<img
className="w-9 h-9 rounded-full border border-gray-500 object-cover"
src={toAbsoluteUrl('/media/avatars/profile.png')}
alt="User avatar"
/>
</MenuToggle>
{DropdownUser({ menuItemRef: itemUserRef })}
</MenuItem>
</Menu>
</div>
<Menu>
<MenuItem
ref={itemUserRef}
toggle="dropdown"
trigger="click"
dropdownProps={{
placement: isRTL() ? 'bottom-start' : 'bottom-end',
modifiers: [
{
name: 'offset',
options: {
offset: [20, 10]
}
}
]
}}
>
<MenuToggle className="btn btn-icon rounded-full">
<img
className="w-9 h-9 rounded-full border border-gray-500 object-cover"
src={toAbsoluteUrl('/media/avatars/profile.png')}
alt="User avatar"
/>
</MenuToggle>
{DropdownUser({ menuItemRef: itemUserRef })}
</MenuItem>
</Menu>
</div>
); );
}; };

View File

@ -25,6 +25,7 @@ import {
CommandList CommandList
} from '@/components/ui/command'; } from '@/components/ui/command';
import { doSaveLogActivity } from '@/actions/GlobalActions'; import { doSaveLogActivity } from '@/actions/GlobalActions';
import { RefreshCw } from 'lucide-react';
interface SucosProps { interface SucosProps {
id: number; id: number;
@ -54,6 +55,7 @@ const AddDialog = () => {
const [formField, setFormField] = useState(initialState); const [formField, setFormField] = useState(initialState);
const created_time = new Date(); const created_time = new Date();
const formattedTime = created_time.toISOString().slice(0, 19).replace('T', ' '); const formattedTime = created_time.toISOString().slice(0, 19).replace('T', ' ');
const [isSubmitting, setIsSubmitting] = useState(false);
const resetForm = () => { const resetForm = () => {
setFormField(initialState); setFormField(initialState);
@ -63,24 +65,31 @@ const AddDialog = () => {
const doCreateAldeias = useCallback( const doCreateAldeias = useCallback(
async (e: React.FormEvent<HTMLFormElement>) => { async (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault(); e.preventDefault();
setIsSubmitting(true);
const response = await PostData(`${API_URL}/aldeias/create`, formField); try {
const response = await PostData(`${API_URL}/aldeias/create`, formField);
if (response?.status) { if (response?.status) {
resetForm(); resetForm();
handleAddDialog(false); handleAddDialog(false);
toast.success('Success Create Aldeia'); toast.success('Success Create Aldeia');
reload(); reload();
const createActivity = {
module: 'Manage Aldeia',
description: `Create Aldeia => ${formField.name}`,
action: 'C'
};
doSaveLogActivity(createActivity); const createActivity = {
} else { module: 'Manage Aldeia',
toast.error('Error Create Aldeia'); description: `Create Aldeia => ${formField.name}`,
setAlert({ show: true, message: 'Failed to create Aldeia. Please try again.' }); action: 'C'
};
doSaveLogActivity(createActivity);
} else {
toast.error('Error Create Aldeia');
setAlert({ show: true, message: response?.message });
}
} catch (error) {
toast.error('Something went wrong');
} finally {
setIsSubmitting(false);
} }
}, },
[formField] [formField]
@ -221,7 +230,13 @@ const AddDialog = () => {
<Button type="button" variant="outline" onClick={resetForm}> <Button type="button" variant="outline" onClick={resetForm}>
Reset Reset
</Button> </Button>
<Button variant="default">Save Changes</Button> <Button variant="default" type="submit" disabled={isSubmitting}>
{isSubmitting ? (
<RefreshCw className="animate-spin h-8 w-8 text-white mx-3" />
) : (
'Create'
)}
</Button>
</div> </div>
</div> </div>
</form> </form>

View File

@ -25,6 +25,7 @@ import {
CommandList CommandList
} from '@/components/ui/command'; } from '@/components/ui/command';
import { doSaveLogActivity } from '@/actions/GlobalActions'; import { doSaveLogActivity } from '@/actions/GlobalActions';
import { RefreshCw } from 'lucide-react';
interface SucosProps { interface SucosProps {
id: number; id: number;
@ -54,6 +55,7 @@ const EditDialog = () => {
const [formField, setFormField] = useState(initialState); const [formField, setFormField] = useState(initialState);
const created_time = new Date(); const created_time = new Date();
const formattedTime = created_time.toISOString().slice(0, 19).replace('T', ' '); const formattedTime = created_time.toISOString().slice(0, 19).replace('T', ' ');
const [isSubmitting, setIsSubmitting] = useState(false);
const resetForm = () => { const resetForm = () => {
setFormField(initialState); setFormField(initialState);
@ -63,24 +65,31 @@ const EditDialog = () => {
const doUpdateAldeias = useCallback( const doUpdateAldeias = useCallback(
async (e: React.FormEvent<HTMLFormElement>) => { async (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault(); e.preventDefault();
setIsSubmitting(true);
const response = await PutData(`${API_URL}/aldeias/update/${selectedAldeias}`, formField); try {
const response = await PutData(`${API_URL}/aldeias/update/${selectedAldeias}`, formField);
if (response?.status) { if (response?.status) {
resetForm(); resetForm();
handleEditDialog(false, null); handleEditDialog(false, null);
toast.success('Success Update Aldeia'); toast.success('Success Update Aldeia');
reload(); reload();
const createActivity = { const createActivity = {
module: 'Manage Aldeia', module: 'Manage Aldeia',
description: `Edit Aldeia => ${selectedAldeias}`, description: `Edit Aldeia => ${selectedAldeias}`,
action: 'U' action: 'U'
}; };
doSaveLogActivity(createActivity); doSaveLogActivity(createActivity);
} else { } else {
toast.error('Error Update Aldeia'); toast.error('Error Update Aldeia');
setAlert({ show: true, message: 'Error Update Aldeia' }); setAlert({ show: true, message: response?.message });
}
} catch (error) {
toast.error('Something went wrong');
} finally {
setIsSubmitting(false);
} }
}, },
[selectedAldeias, formField] [selectedAldeias, formField]
@ -258,7 +267,13 @@ const EditDialog = () => {
</div> </div>
<div className="flex justify-end"> <div className="flex justify-end">
<Button className="btn btn-primary">Save Changes</Button> <Button variant="default" type="submit" disabled={isSubmitting}>
{isSubmitting ? (
<RefreshCw className="animate-spin h-8 w-8 text-white mx-7" />
) : (
'Save Changes'
)}
</Button>
</div> </div>
</div> </div>
</form> </form>

View File

@ -34,6 +34,7 @@ import {
} from '@/components/ui/select'; } from '@/components/ui/select';
import { useManageConversionContext } from '../hooks/useManageConversionContext'; import { useManageConversionContext } from '../hooks/useManageConversionContext';
import { doSaveLogActivity } from '@/actions/GlobalActions'; import { doSaveLogActivity } from '@/actions/GlobalActions';
import { RefreshCw } from 'lucide-react';
interface CurrencyProps { interface CurrencyProps {
ID: string; ID: string;
name: string; name: string;
@ -65,6 +66,7 @@ const AddDialog = () => {
const [formField, setFormField] = useState(initialState); const [formField, setFormField] = useState(initialState);
const created_time = new Date(); const created_time = new Date();
const formattedTime = created_time.toISOString().slice(0, 19).replace('T', ' '); const formattedTime = created_time.toISOString().slice(0, 19).replace('T', ' ');
const [isSubmitting, setIsSubmitting] = useState(false);
const resetForm = () => { const resetForm = () => {
setFormField(initialState); setFormField(initialState);
@ -74,24 +76,31 @@ const AddDialog = () => {
const doCreateConversion = useCallback( const doCreateConversion = useCallback(
async (e: React.FormEvent<HTMLFormElement>) => { async (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault(); e.preventDefault();
setIsSubmitting(true);
const response = await PostData(`${API_URL}/dashboard/conversion`, formField); try {
const response = await PostData(`${API_URL}/dashboard/conversion`, formField);
if (response?.status) { if (response?.status) {
resetForm(); resetForm();
handleAddDialog(false); handleAddDialog(false);
toast.success('Success Create Conversion'); toast.success('Success Create Conversion');
const createActivity = { const createActivity = {
module: 'Manage Conversion', module: 'Manage Conversion',
description: `Create Conversion => ${formField.id_currency_origin} => ${formField.id_currency_destination}`, description: `Create Conversion => ${formField.id_currency_origin} => ${formField.id_currency_destination}`,
action: 'C' action: 'C'
}; };
doSaveLogActivity(createActivity); doSaveLogActivity(createActivity);
reload(); reload();
} else { } else {
toast.error('Error Create Conversion'); toast.error('Error Create Conversion');
setAlert({ show: true, message: 'Failed to create Conversion. Please try again.' }); setAlert({ show: true, message: response?.message });
}
} catch (error) {
toast.error('Something Went Wrong');
} finally {
setIsSubmitting(false);
} }
}, },
[formField] [formField]
@ -280,7 +289,13 @@ const AddDialog = () => {
<Button type="button" variant="outline" onClick={resetForm}> <Button type="button" variant="outline" onClick={resetForm}>
Reset Reset
</Button> </Button>
<Button variant="default">Save Changes</Button> <Button variant="default" type="submit" disabled={isSubmitting}>
{isSubmitting ? (
<RefreshCw className="animate-spin h-8 w-8 text-white mx-3" />
) : (
'Create'
)}
</Button>
</div> </div>
</div> </div>
</form> </form>

View File

@ -34,6 +34,7 @@ import {
} from '@/components/ui/select'; } from '@/components/ui/select';
import { useManageConversionContext } from '../hooks/useManageConversionContext'; import { useManageConversionContext } from '../hooks/useManageConversionContext';
import { doSaveLogActivity } from '@/actions/GlobalActions'; import { doSaveLogActivity } from '@/actions/GlobalActions';
import { RefreshCw } from 'lucide-react';
interface CurrencyProps { interface CurrencyProps {
ID: string; ID: string;
name: string; name: string;
@ -49,6 +50,7 @@ const EditDialog = () => {
const parsedUser = getAuth()?.user; const parsedUser = getAuth()?.user;
const [currencies, setCurrencies] = useState<CurrencyProps[]>([]); const [currencies, setCurrencies] = useState<CurrencyProps[]>([]);
const [open, setOpen] = useState(false); const [open, setOpen] = useState(false);
const [isSubmitting, setIsSubmitting] = useState(false);
const [isLoading, setIsLoading] = useState(false); const [isLoading, setIsLoading] = useState(false);
const [alert, setAlert] = useState({ const [alert, setAlert] = useState({
show: false, show: false,
@ -75,26 +77,33 @@ const EditDialog = () => {
const doUpdateConversion = useCallback( const doUpdateConversion = useCallback(
async (e: React.FormEvent<HTMLFormElement>) => { async (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault(); e.preventDefault();
if (!showEditDialog) return; setIsSubmitting(true);
const response = await PutData(`${API_URL}/dashboard/conversion/${selectedConversion}`, {
...formField
});
if (response?.status) { try {
resetForm(); const response = await PutData(`${API_URL}/dashboard/conversion/${selectedConversion}`, {
handleEditDialog(false, null); ...formField
toast.success('Success Update Conversion'); });
const createActivity = {
module: 'Manage Conversion',
description: `Update Conversion => ${selectedConversion}`,
action: 'U'
};
doSaveLogActivity(createActivity); if (response?.status) {
reload(); resetForm();
} else { handleEditDialog(false, null);
toast.error('Error Create Conversion'); toast.success('Success Update Conversion');
setAlert({ show: true, message: 'Failed to Update Conversion. Please try again.' }); const createActivity = {
module: 'Manage Conversion',
description: `Update Conversion => ${selectedConversion}`,
action: 'U'
};
doSaveLogActivity(createActivity);
reload();
} else {
toast.error('Error Create Conversion');
setAlert({ show: true, message: response?.message });
}
} catch (error) {
toast.error('Something went wrong');
} finally {
setIsSubmitting(false);
} }
}, },
[formField] [formField]
@ -305,7 +314,13 @@ const EditDialog = () => {
</div> </div>
</div> </div>
<div className="flex justify-end gap-5"> <div className="flex justify-end gap-5">
<Button variant="default">Save Changes</Button> <Button variant="default" type="submit" disabled={isSubmitting}>
{isSubmitting ? (
<RefreshCw className="animate-spin h-8 w-8 text-white mx-7" />
) : (
'Create'
)}
</Button>
</div> </div>
</div> </div>
</form> </form>

View File

@ -35,6 +35,7 @@ import {
import { useManageCurrencyContext } from '../hooks/useManageCurrencyContext'; import { useManageCurrencyContext } from '../hooks/useManageCurrencyContext';
import { prefix } from 'stylis'; import { prefix } from 'stylis';
import { doSaveLogActivity } from '@/actions/GlobalActions'; import { doSaveLogActivity } from '@/actions/GlobalActions';
import { RefreshCw } from 'lucide-react';
interface CurrencyProps { interface CurrencyProps {
ID: string; ID: string;
name: string; name: string;
@ -50,6 +51,7 @@ const AddDialog = () => {
const parsedUser = getAuth()?.user; const parsedUser = getAuth()?.user;
const [currencies, setCurrencies] = useState<CurrencyProps[]>([]); const [currencies, setCurrencies] = useState<CurrencyProps[]>([]);
const [open, setOpen] = useState(false); const [open, setOpen] = useState(false);
const [isSubmitting, setIsSubmitting] = useState(false);
const [alert, setAlert] = useState({ const [alert, setAlert] = useState({
show: false, show: false,
message: '' message: ''
@ -74,24 +76,31 @@ const AddDialog = () => {
const doCreateCurrency = useCallback( const doCreateCurrency = useCallback(
async (e: React.FormEvent<HTMLFormElement>) => { async (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault(); e.preventDefault();
setIsSubmitting(true);
const response = await PostData(`${API_URL}/dashboard/currency/`, formField); try {
const response = await PostData(`${API_URL}/dashboard/currency/`, formField);
if (response?.status) { if (response?.status) {
resetForm(); resetForm();
handleAddDialog(false); handleAddDialog(false);
toast.success('Success Create Currency'); toast.success('Success Create Currency');
const createActivity = { const createActivity = {
module: 'Manage Currency', module: 'Manage Currency',
description: `Create Currency=> ${formField.name}`, description: `Create Currency=> ${formField.name}`,
action: 'C' action: 'C'
}; };
doSaveLogActivity(createActivity); doSaveLogActivity(createActivity);
reload(); reload();
} else { } else {
toast.error('Error Create Currency'); toast.error('Error Create Currency');
setAlert({ show: true, message: 'Failed to create Currency. Please try again.' }); setAlert({ show: true, message: response?.message });
}
} catch (error) {
toast.error('Something went wrong');
} finally {
setIsSubmitting(false);
} }
}, },
[formField] [formField]
@ -220,7 +229,13 @@ const AddDialog = () => {
<Button type="button" variant="outline" onClick={resetForm}> <Button type="button" variant="outline" onClick={resetForm}>
Reset Reset
</Button> </Button>
<Button variant="default">Save Changes</Button> <Button variant="default" type="submit" disabled={isSubmitting}>
{isSubmitting ? (
<RefreshCw className="animate-spin h-8 w-8 text-white mx-3" />
) : (
'Create'
)}
</Button>
</div> </div>
</div> </div>
</form> </form>

View File

@ -34,6 +34,7 @@ import {
} from '@/components/ui/select'; } from '@/components/ui/select';
import { useManageCurrencyContext } from '../hooks/useManageCurrencyContext'; import { useManageCurrencyContext } from '../hooks/useManageCurrencyContext';
import { doSaveLogActivity } from '@/actions/GlobalActions'; import { doSaveLogActivity } from '@/actions/GlobalActions';
import { RefreshCw } from 'lucide-react';
interface CurrencyProps { interface CurrencyProps {
ID: string; ID: string;
name: string; name: string;
@ -49,6 +50,7 @@ const EditDialog = () => {
const parsedUser = getAuth()?.user; const parsedUser = getAuth()?.user;
const [currencies, setCurrencies] = useState<CurrencyProps[]>([]); const [currencies, setCurrencies] = useState<CurrencyProps[]>([]);
const [open, setOpen] = useState(false); const [open, setOpen] = useState(false);
const [isSubmitting, setIsSubmitting] = useState(false);
const [isLoading, setIsLoading] = useState(false); const [isLoading, setIsLoading] = useState(false);
const [alert, setAlert] = useState({ const [alert, setAlert] = useState({
show: false, show: false,
@ -74,26 +76,34 @@ const EditDialog = () => {
const doUpdateCurrency = useCallback( const doUpdateCurrency = useCallback(
async (e: React.FormEvent<HTMLFormElement>) => { async (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault(); e.preventDefault();
if (!showEditDialog) return; setIsSubmitting(true);
const response = await PutData(`${API_URL}/dashboard/currency/${selectedCurrency}`, {
...formField
});
if (response?.status) { try {
resetForm(); const response = await PutData(
handleEditDialog(false, null); `${API_URL}/dashboard/currency/${selectedCurrency}`,
toast.success('Success Update Currency'); formField
const createActivity = { );
module: 'Manage Currency',
description: `Update Currency=> ${selectedCurrency}`,
action: 'U'
};
doSaveLogActivity(createActivity); if (response?.status) {
reload(); resetForm();
} else { handleEditDialog(false, null);
toast.error('Error Create Currency'); toast.success('Success Update Currency');
setAlert({ show: true, message: 'Failed to Update Currency. Please try again.' }); const createActivity = {
module: 'Manage Currency',
description: `Update Currency=> ${selectedCurrency}`,
action: 'U'
};
doSaveLogActivity(createActivity);
reload();
} else {
toast.error('Error Create Currency');
setAlert({ show: true, message: response?.message });
}
} catch (error) {
toast.error('Something went wrong');
} finally {
setIsSubmitting(false);
} }
}, },
[formField] [formField]
@ -235,7 +245,13 @@ const EditDialog = () => {
</div> </div>
<div className="flex justify-end gap-5"> <div className="flex justify-end gap-5">
<Button variant="default">Save Changes</Button> <Button variant="default" type="submit" disabled={isSubmitting}>
{isSubmitting ? (
<RefreshCw className="animate-spin h-8 w-8 text-white mx-7" />
) : (
'Save Changes'
)}
</Button>
</div> </div>
</div> </div>
</form> </form>

View File

@ -17,6 +17,7 @@ import { toast } from 'sonner';
import { getAuth, useAuthContext } from '@/auth'; import { getAuth, useAuthContext } from '@/auth';
import { useCallApi } from '@/hooks'; import { useCallApi } from '@/hooks';
import { doSaveLogActivity } from '@/actions/GlobalActions'; import { doSaveLogActivity } from '@/actions/GlobalActions';
import { RefreshCw } from 'lucide-react';
const API_URL = apiConfig.service_master_data; const API_URL = apiConfig.service_master_data;
@ -39,6 +40,7 @@ const AddDialog = () => {
const [formField, setFormField] = useState(initialState); const [formField, setFormField] = useState(initialState);
const created_time = new Date(); const created_time = new Date();
const formattedTime = created_time.toISOString().slice(0, 19).replace('T', ' '); const formattedTime = created_time.toISOString().slice(0, 19).replace('T', ' ');
const [isSubmitting, setIsSubmitting] = useState(false);
const resetForm = () => { const resetForm = () => {
setFormField(initialState); setFormField(initialState);
@ -48,23 +50,31 @@ const AddDialog = () => {
const doCreateMunicipio = useCallback( const doCreateMunicipio = useCallback(
async (e: React.FormEvent<HTMLFormElement>) => { async (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault(); e.preventDefault();
const response = await PostData(`${API_URL}/municipios/create`, formField); setIsSubmitting(true);
if (response?.status) { try {
handleAddDialog(false); const response = await PostData(`${API_URL}/municipios/create`, formField);
resetForm();
reload();
toast.success('Municipio created successfully!');
const createActivity = {
module: 'Manage Municipio',
description: `Create Municipio => ${formField.name}`,
action: 'C'
};
doSaveLogActivity(createActivity); if (response?.status) {
} else { handleAddDialog(false);
toast.error('Failed to create municipio.'); resetForm();
setAlert({ show: true, message: 'Failed to create municipio. Please try again.' }); reload();
toast.success('Municipio created successfully!');
const createActivity = {
module: 'Manage Municipio',
description: `Create Municipio => ${formField.name}`,
action: 'C'
};
doSaveLogActivity(createActivity);
} else {
toast.error('Failed to create municipio.');
setAlert({ show: true, message: response?.message });
}
} catch (error) {
toast.error('Something went wrong. Please try again.');
} finally {
setIsSubmitting(false);
} }
}, },
[formField] [formField]
@ -140,8 +150,12 @@ const AddDialog = () => {
<Button variant={'outline'} type="reset" onClick={handleReset}> <Button variant={'outline'} type="reset" onClick={handleReset}>
Reset Reset
</Button> </Button>
<Button variant={'default'} type="submit"> <Button variant="default" type="submit" disabled={isSubmitting}>
Create {isSubmitting ? (
<RefreshCw className="animate-spin h-8 w-8 text-white mx-3" />
) : (
'Create'
)}
</Button> </Button>
</div> </div>
</div> </div>

View File

@ -17,6 +17,7 @@ import { Button } from '@/components/ui/button';
import { getAuth, useAuthContext } from '@/auth'; import { getAuth, useAuthContext } from '@/auth';
import { useCallApi } from '@/hooks'; import { useCallApi } from '@/hooks';
import { doSaveLogActivity } from '@/actions/GlobalActions'; import { doSaveLogActivity } from '@/actions/GlobalActions';
import { RefreshCw } from 'lucide-react';
const API_URL = apiConfig.service_master_data; const API_URL = apiConfig.service_master_data;
@ -27,6 +28,7 @@ const EditDialog = () => {
const { PutData, GetData } = useCallApi(); const { PutData, GetData } = useCallApi();
const parsedUser = getAuth()?.user; const parsedUser = getAuth()?.user;
const [isLoading, setIsLoading] = useState(false); const [isLoading, setIsLoading] = useState(false);
const [isSubmitting, setIsSubmitting] = useState(false);
const [alert, setAlert] = useState({ const [alert, setAlert] = useState({
show: false, show: false,
message: '' message: ''
@ -50,26 +52,34 @@ const EditDialog = () => {
const doUpdateMunicipios = useCallback( const doUpdateMunicipios = useCallback(
async (e: React.FormEvent<HTMLFormElement>) => { async (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault(); e.preventDefault();
const response = await PutData( setIsSubmitting(true);
`${API_URL}/municipios/update/${selectedMunicipios}`,
formField
);
if (response?.status) { try {
handleEditDialog(false, null); const response = await PutData(
resetForm(); `${API_URL}/municipios/update/${selectedMunicipios}`,
toast.success('Success update municipio'); formField
reload(); );
const createActivity = {
module: 'Manage Municipios',
description: `Edit Municipio => ${selectedMunicipios}`,
action: 'U'
};
doSaveLogActivity(createActivity); if (response?.status) {
} else { handleEditDialog(false, null);
toast.error('Failed update user'); resetForm();
setAlert({ show: true, message: 'Failed to update municipio. Please try again.' }); toast.success('Success update municipio');
reload();
const createActivity = {
module: 'Manage Municipios',
description: `Edit Municipio => ${selectedMunicipios}`,
action: 'U'
};
doSaveLogActivity(createActivity);
} else {
toast.error('Failed update user');
setAlert({ show: true, message: response?.message });
}
} catch (error) {
toast.error('Something went wrong, please try again.');
} finally {
setIsSubmitting(false);
} }
}, },
[selectedMunicipios, formField] [selectedMunicipios, formField]
@ -177,7 +187,13 @@ const EditDialog = () => {
</div> </div>
<div className="flex justify-end pt-2.5"> <div className="flex justify-end pt-2.5">
<Button className="btn btn-primary">Save Changes</Button> <Button variant="default" type="submit" disabled={isSubmitting}>
{isSubmitting ? (
<RefreshCw className="animate-spin h-8 w-8 text-white mx-7" />
) : (
'Save Changes'
)}
</Button>
</div> </div>
</div> </div>
</form> </form>

View File

@ -25,6 +25,7 @@ import {
CommandList CommandList
} from '@/components/ui/command'; } from '@/components/ui/command';
import { doSaveLogActivity } from '@/actions/GlobalActions'; import { doSaveLogActivity } from '@/actions/GlobalActions';
import { RefreshCw } from 'lucide-react';
interface MunicipioProps { interface MunicipioProps {
id: number; id: number;
@ -41,6 +42,7 @@ const AddDialog = () => {
const parsedUser = getAuth()?.user; const parsedUser = getAuth()?.user;
const [municipios, setMunicipios] = useState<MunicipioProps[]>([]); const [municipios, setMunicipios] = useState<MunicipioProps[]>([]);
const [open, setOpen] = useState(false); const [open, setOpen] = useState(false);
const [isSubmitting, setIsSubmitting] = useState(false);
const [alert, setAlert] = useState({ const [alert, setAlert] = useState({
show: false, show: false,
message: '' message: ''
@ -65,27 +67,34 @@ const AddDialog = () => {
const doCreatePostoAdm = useCallback( const doCreatePostoAdm = useCallback(
async (e: React.FormEvent<HTMLFormElement>) => { async (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault(); e.preventDefault();
setIsSubmitting(true);
const response = await PostData(`${API_URL}/postoadms/create`, formField); try {
const response = await PostData(`${API_URL}/postoadms/create`, formField);
if (response?.status) { if (response?.status) {
handleAddDialog(false); handleAddDialog(false);
resetForm(); resetForm();
reload(); reload();
toast.success('Postu Administrativo created successfully!'); toast.success('Postu Administrativo created successfully!');
const createActivity = { const createActivity = {
module: 'Manage Posto Administrativo', module: 'Manage Posto Administrativo',
description: `Create Postu Administrativo => ${formField.name}`, description: `Create Postu Administrativo => ${formField.name}`,
action: 'C' action: 'C'
}; };
doSaveLogActivity(createActivity); doSaveLogActivity(createActivity);
} else { } else {
toast.error('Failed to create Postu Administrativo. Please try again.'); toast.error('Failed to create Postu Administrativo. Please try again.');
setAlert({ setAlert({
show: true, show: true,
message: 'Failed to create Postu Administrativo. Please try again.' message: response?.message
}); });
}
} catch (error) {
toast.error('Something went wrong. Please try again.');
} finally {
setIsSubmitting(false);
} }
}, },
[formField] [formField]
@ -222,7 +231,13 @@ const AddDialog = () => {
<Button type="button" variant="outline" onClick={resetForm}> <Button type="button" variant="outline" onClick={resetForm}>
Reset Reset
</Button> </Button>
<Button variant="default">Save Changes</Button> <Button variant="default" type="submit" disabled={isSubmitting}>
{isSubmitting ? (
<RefreshCw className="animate-spin h-8 w-8 text-white mx-3" />
) : (
'Create'
)}
</Button>
</div> </div>
</div> </div>
</form> </form>

View File

@ -25,6 +25,7 @@ import {
CommandList CommandList
} from '@/components/ui/command'; } from '@/components/ui/command';
import { doSaveLogActivity } from '@/actions/GlobalActions'; import { doSaveLogActivity } from '@/actions/GlobalActions';
import { RefreshCw } from 'lucide-react';
interface MunicipioProps { interface MunicipioProps {
id: number; id: number;
@ -43,6 +44,7 @@ const EditDialog = () => {
const [open, setOpen] = useState(false); const [open, setOpen] = useState(false);
const [isLoading, setIsLoading] = useState(false); const [isLoading, setIsLoading] = useState(false);
const [municipios, setMunicipios] = useState<MunicipioProps[]>([]); const [municipios, setMunicipios] = useState<MunicipioProps[]>([]);
const [isSubmitting, setIsSubmitting] = useState(false);
const [alert, setAlert] = useState({ const [alert, setAlert] = useState({
show: false, show: false,
@ -66,28 +68,38 @@ const EditDialog = () => {
const doUpdatePostoAdm = useCallback( const doUpdatePostoAdm = useCallback(
async (e: React.FormEvent<HTMLFormElement>) => { async (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault(); e.preventDefault();
setIsSubmitting(true);
const response = await PutData(`${API_URL}/postoadms/update/${selectedPostoAdms}`, formField); try {
const response = await PutData(
`${API_URL}/postoadms/update/${selectedPostoAdms}`,
formField
);
if (response?.status) { if (response?.status) {
handleEditDialog(false, null); handleEditDialog(false, null);
resetForm(); resetForm();
toast.success('Success Update Postu Administrativo'); toast.success('Success Update Postu Administrativo');
reload(); reload();
const createActivity = { const createActivity = {
module: 'Manage Postu Administrativo', module: 'Manage Postu Administrativo',
description: `Edit Postu Administrativo => ${selectedPostoAdms}`, description: `Edit Postu Administrativo => ${selectedPostoAdms}`,
action: 'U' action: 'U'
}; };
doSaveLogActivity(createActivity); doSaveLogActivity(createActivity);
} else { } else {
toast.error('Error Update Postu Administrativo'); toast.error('Error Update Postu Administrativo');
setAlert({ setAlert({
show: true, show: true,
message: 'Failed to update Postu Administrativo Please try again.' message: response?.message
}); });
}
} catch (error) {
toast.error('Something went wrong, please try again');
} finally {
setIsSubmitting(false);
} }
}, },
[selectedPostoAdms, formField] [selectedPostoAdms, formField]
@ -261,7 +273,13 @@ const EditDialog = () => {
</div> </div>
<div className="flex justify-end gap-5"> <div className="flex justify-end gap-5">
<Button className="btn btn-primary">Save Changes</Button> <Button variant="default" type="submit" disabled={isSubmitting}>
{isSubmitting ? (
<RefreshCw className="animate-spin h-8 w-8 text-white mx-7" />
) : (
'Save Changes'
)}
</Button>
</div> </div>
</div> </div>
</form> </form>

View File

@ -24,6 +24,7 @@ import {
} from '@/components/ui/select'; } from '@/components/ui/select';
import { doSaveLogActivity } from '@/actions/GlobalActions'; import { doSaveLogActivity } from '@/actions/GlobalActions';
import { NumericFormat } from 'react-number-format'; import { NumericFormat } from 'react-number-format';
import { RefreshCw } from 'lucide-react';
interface ProviderProps { interface ProviderProps {
provider_id: number; provider_id: number;
@ -72,6 +73,7 @@ const AddDialog = () => {
}; };
const [formField, setFormField] = useState(initialState); const [formField, setFormField] = useState(initialState);
const [providers, setProviders] = useState<ProviderProps[]>([]); const [providers, setProviders] = useState<ProviderProps[]>([]);
const [isSubmitting, setIsSubmitting] = useState(false);
const created_time = new Date(); const created_time = new Date();
const formattedTime = created_time.toISOString().slice(0, 19).replace('T', ' '); const formattedTime = created_time.toISOString().slice(0, 19).replace('T', ' ');
@ -83,25 +85,32 @@ const AddDialog = () => {
const doCreateProduct = useCallback( const doCreateProduct = useCallback(
async (e: React.FormEvent<HTMLFormElement>) => { async (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault(); e.preventDefault();
setIsSubmitting(true);
const response = await PostData(`${API_URL}/product/create`, formField); try {
const response = await PostData(`${API_URL}/product/create`, formField);
if (response?.status) { if (response?.status) {
resetForm(); resetForm();
handleAddDialog(false); handleAddDialog(false);
toast.success('Success Create Product'); toast.success('Success Create Product');
reload(); reload();
const createActivity = { const createActivity = {
module: 'Manage Products', module: 'Manage Products',
description: `Create Product => ${formField.name}`, description: `Create Product => ${formField.name}`,
action: 'C' action: 'C'
}; };
doSaveLogActivity(createActivity); doSaveLogActivity(createActivity);
} else { } else {
toast.error('Failed Create Product'); toast.error('Failed Create Product');
setAlert({ show: true, message: response?.message }); setAlert({ show: true, message: response?.message });
}
} catch (error) {
toast.error('Something went wrong, please try again.');
} finally {
setIsSubmitting(false);
} }
}, },
[formField] [formField]
@ -356,9 +365,7 @@ const AddDialog = () => {
<div className="w-full"> <div className="w-full">
<div className="flex items-baseline flex-wrap lg:flex-nowrap gap-2.5"> <div className="flex items-baseline flex-wrap lg:flex-nowrap gap-2.5">
<label className="form-label flex items-center gap-1 max-w-56"> <label className="form-label flex items-center gap-1 max-w-56">Provider</label>
Provider ID
</label>
<Select <Select
value={formField.provider} value={formField.provider}
onValueChange={(value) => onValueChange={(value) =>
@ -408,7 +415,13 @@ const AddDialog = () => {
<Button type="button" variant="outline" onClick={resetForm}> <Button type="button" variant="outline" onClick={resetForm}>
Reset Reset
</Button> </Button>
<Button variant="default">Save Changes</Button> <Button variant="default" type="submit" disabled={isSubmitting}>
{isSubmitting ? (
<RefreshCw className="animate-spin h-8 w-8 text-white mx-7" />
) : (
'Create'
)}
</Button>
</div> </div>
</div> </div>
</form> </form>

View File

@ -24,6 +24,7 @@ import {
} from '@/components/ui/select'; } from '@/components/ui/select';
import { doSaveLogActivity } from '@/actions/GlobalActions'; import { doSaveLogActivity } from '@/actions/GlobalActions';
import { NumericFormat } from 'react-number-format'; import { NumericFormat } from 'react-number-format';
import { RefreshCw } from 'lucide-react';
interface ProviderProps { interface ProviderProps {
provider_id: string; provider_id: string;
@ -37,6 +38,7 @@ const EditDialog = () => {
const { PutData, GetData } = useCallApi(); const { PutData, GetData } = useCallApi();
const parsedUser = getAuth()?.user; const parsedUser = getAuth()?.user;
const [isLoading, setIsLoading] = useState(false); const [isLoading, setIsLoading] = useState(false);
const [isSubmitting, setIsSubmitting] = useState(false);
const created_time = new Date(); const created_time = new Date();
const formattedTime = created_time.toISOString().slice(0, 19).replace('T', ' '); const formattedTime = created_time.toISOString().slice(0, 19).replace('T', ' ');
const [alert, setAlert] = useState({ const [alert, setAlert] = useState({
@ -83,25 +85,32 @@ const EditDialog = () => {
const doUpdateProduct = useCallback( const doUpdateProduct = useCallback(
async (e: React.FormEvent<HTMLFormElement>) => { async (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault(); e.preventDefault();
setIsSubmitting(true);
const response = await PutData(`${API_URL}/product/update/${selectedProducts}`, formField); try {
const response = await PutData(`${API_URL}/product/update/${selectedProducts}`, formField);
if (response?.status) { if (response?.status) {
resetForm(); resetForm();
handleEditDialog(false, null); handleEditDialog(false, null);
toast.success('Product updated successfully.'); toast.success('Product updated successfully.');
reload(); reload();
const createActivity = { const createActivity = {
module: 'Manage Products', module: 'Manage Products',
description: `Edit Product => ${selectedProducts}`, description: `Edit Product => ${selectedProducts}`,
action: 'U' action: 'U'
}; };
doSaveLogActivity(createActivity); doSaveLogActivity(createActivity);
} else { } else {
toast.error('Failed to update Product. Please try again.'); toast.error('Failed to update Product. Please try again.');
setAlert({ show: true, message: 'Failed to update Product. Please try again.' }); setAlert({ show: true, message: response?.message });
}
} catch (error) {
toast.error('Something went wrong. Please try again.');
} finally {
setIsSubmitting(false);
} }
}, },
[selectedProducts, formField] [selectedProducts, formField]
@ -406,7 +415,7 @@ const EditDialog = () => {
<div className="w-full"> <div className="w-full">
<div className="flex items-baseline flex-wrap lg:flex-nowrap gap-2.5"> <div className="flex items-baseline flex-wrap lg:flex-nowrap gap-2.5">
<label className="form-label flex items-center gap-1 max-w-56"> <label className="form-label flex items-center gap-1 max-w-56">
Provider ID Provider
</label> </label>
<Select <Select
value={formField.provider} value={formField.provider}
@ -449,7 +458,13 @@ const EditDialog = () => {
</div> </div>
<div className="flex justify-end gap-5"> <div className="flex justify-end gap-5">
<Button variant="default">Save Changes</Button> <Button variant="default" type="submit" disabled={isSubmitting}>
{isSubmitting ? (
<RefreshCw className="animate-spin h-8 w-8 text-white mx-7" />
) : (
'Save Changes'
)}
</Button>
</div> </div>
</div> </div>
</form> </form>

View File

@ -16,6 +16,7 @@ import {
import { Input } from '@/components/ui/input'; import { Input } from '@/components/ui/input';
import { Button } from '@/components/ui/button'; import { Button } from '@/components/ui/button';
import { doSaveLogActivity } from '@/actions/GlobalActions'; import { doSaveLogActivity } from '@/actions/GlobalActions';
import { RefreshCw } from 'lucide-react';
const API_URL = apiConfig.service_master_data; const API_URL = apiConfig.service_master_data;
const AddDialog = () => { const AddDialog = () => {
@ -35,6 +36,7 @@ const AddDialog = () => {
created_at: '' created_at: ''
}; };
const [formField, setFormField] = useState(initialState); const [formField, setFormField] = useState(initialState);
const [isSubmitting, setIsSubmitting] = useState(false);
const created_time = new Date(); const created_time = new Date();
const formattedTime = created_time.toISOString().slice(0, 19).replace('T', ' '); const formattedTime = created_time.toISOString().slice(0, 19).replace('T', ' ');
@ -46,25 +48,32 @@ const AddDialog = () => {
const doCreateProfession = useCallback( const doCreateProfession = useCallback(
async (e: React.FormEvent<HTMLFormElement>) => { async (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault(); e.preventDefault();
setIsSubmitting(true);
const response = await PostData(`${API_URL}/profession/create`, formField); try {
const response = await PostData(`${API_URL}/profession/create`, formField);
if (response?.status) { if (response?.status) {
resetForm(); resetForm();
handleAddDialog(false); handleAddDialog(false);
toast.success('Success Create Profession'); toast.success('Success Create Profession');
reload(); reload();
const createActivity = { const createActivity = {
module: 'Manage Profession', module: 'Manage Profession',
description: `Create Profession => ${formField.name}`, description: `Create Profession => ${formField.name}`,
action: 'C' action: 'C'
}; };
doSaveLogActivity(createActivity); doSaveLogActivity(createActivity);
} else { } else {
toast.error('Failed Create Profession'); toast.error('Failed Create Profession');
setAlert({ show: true, message: response?.message }); setAlert({ show: true, message: response?.message });
}
} catch (error) {
toast.error('Something went wrong, please try again.');
} finally {
setIsSubmitting(false);
} }
}, },
[formField] [formField]
@ -134,7 +143,13 @@ const AddDialog = () => {
<Button type="button" variant="outline" onClick={resetForm}> <Button type="button" variant="outline" onClick={resetForm}>
Reset Reset
</Button> </Button>
<Button variant="default">Create</Button> <Button variant="default" type="submit" disabled={isSubmitting}>
{isSubmitting ? (
<RefreshCw className="animate-spin h-8 w-8 text-white mx-3" />
) : (
'Create'
)}
</Button>
</div> </div>
</div> </div>
</form> </form>

View File

@ -16,6 +16,7 @@ import {
import { Input } from '@/components/ui/input'; import { Input } from '@/components/ui/input';
import { Button } from '@/components/ui/button'; import { Button } from '@/components/ui/button';
import { doSaveLogActivity } from '@/actions/GlobalActions'; import { doSaveLogActivity } from '@/actions/GlobalActions';
import { RefreshCw } from 'lucide-react';
const API_URL = apiConfig.service_master_data; const API_URL = apiConfig.service_master_data;
const EditDialog = () => { const EditDialog = () => {
@ -24,6 +25,7 @@ const EditDialog = () => {
const { PutData, GetData } = useCallApi(); const { PutData, GetData } = useCallApi();
const parsedUser = getAuth()?.user; const parsedUser = getAuth()?.user;
const [isLoading, setIsLoading] = useState(false); const [isLoading, setIsLoading] = useState(false);
const [isSubmitting, setIsSubmitting] = useState(false);
const created_time = new Date(); const created_time = new Date();
const formattedTime = created_time.toISOString().slice(0, 19).replace('T', ' '); const formattedTime = created_time.toISOString().slice(0, 19).replace('T', ' ');
const [alert, setAlert] = useState({ const [alert, setAlert] = useState({
@ -45,28 +47,35 @@ const EditDialog = () => {
const doUpdateProfession = useCallback( const doUpdateProfession = useCallback(
async (e: React.FormEvent<HTMLFormElement>) => { async (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault(); e.preventDefault();
setIsSubmitting(true);
const response = await PutData( try {
`${API_URL}/profession/update/${selectedProfession}`, const response = await PutData(
formField `${API_URL}/profession/update/${selectedProfession}`,
); formField
);
if (response?.status) { if (response?.status) {
resetForm(); resetForm();
handleEditDialog(false, null); handleEditDialog(false, null);
toast.success('Success Update Profession'); toast.success('Success Update Profession');
reload(); reload();
const createActivity = { const createActivity = {
module: 'Manage Profession', module: 'Manage Profession',
description: `Edit Profession => ${selectedProfession}`, description: `Edit Profession => ${selectedProfession}`,
action: 'U' action: 'U'
}; };
doSaveLogActivity(createActivity); doSaveLogActivity(createActivity);
} else { } else {
toast.error('Failed Update Profession'); toast.error('Failed Update Profession');
setAlert({ show: true, message: 'Failed Update Profession' }); setAlert({ show: true, message: response?.message });
}
} catch (error) {
toast.error('Something went wrong, please try again.');
} finally {
setIsSubmitting(false);
} }
}, },
[selectedProfession, formField] [selectedProfession, formField]
@ -170,7 +179,13 @@ const EditDialog = () => {
</div> </div>
<div className="flex justify-end"> <div className="flex justify-end">
<Button className="btn btn-primary">Save Changes</Button> <Button variant="default" type="submit" disabled={isSubmitting}>
{isSubmitting ? (
<RefreshCw className="animate-spin h-8 w-8 text-white mx-7" />
) : (
'Save Changes'
)}
</Button>
</div> </div>
</div> </div>
</form> </form>

View File

@ -32,6 +32,7 @@ import {
CommandList CommandList
} from '@/components/ui/command'; } from '@/components/ui/command';
import { doSaveLogActivity } from '@/actions/GlobalActions'; import { doSaveLogActivity } from '@/actions/GlobalActions';
import { RefreshCw } from 'lucide-react';
export interface CustomerProps { export interface CustomerProps {
id: string; id: string;
@ -57,6 +58,7 @@ const AddDialog = () => {
const parentRef = useRef<any | null>(null); const parentRef = useRef<any | null>(null);
const parsedUser = getAuth()?.user; const parsedUser = getAuth()?.user;
const [open, setOpen] = useState(false); const [open, setOpen] = useState(false);
const [isSubmitting, setIsSubmitting] = useState(false);
const [alert, setAlert] = useState({ const [alert, setAlert] = useState({
show: false, show: false,
message: '' message: ''
@ -96,24 +98,31 @@ const AddDialog = () => {
const doCreateProvider = useCallback( const doCreateProvider = useCallback(
async (e: React.FormEvent<HTMLFormElement>) => { async (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault(); e.preventDefault();
setIsSubmitting(true);
const response = await PostData(`${API_URL_MASTERDATA}/provider/create`, formField); try {
const response = await PostData(`${API_URL_MASTERDATA}/provider/create`, formField);
if (response?.status) { if (response?.status) {
resetForm(); resetForm();
handleAddDialog(false); handleAddDialog(false);
toast.success('Success Create Provider'); toast.success('Success Create Provider');
const createActivity = { const createActivity = {
module: 'Manage Provider', module: 'Manage Provider',
description: `Create Provider => ${formField.name}`, description: `Create Provider => ${formField.name}`,
action: 'C' action: 'C'
}; };
doSaveLogActivity(createActivity); doSaveLogActivity(createActivity);
reload(); reload();
} else { } else {
toast.error('Failed Create Provider'); toast.error('Failed Create Provider');
setAlert({ show: true, message: 'Failed Create Provider' }); setAlert({ show: true, message: response?.message });
}
} catch (error) {
toast.error('Something went wrong, please try again.');
} finally {
setIsSubmitting(false);
} }
}, },
[formField] [formField]
@ -282,7 +291,7 @@ const AddDialog = () => {
<div className="w-full"> <div className="w-full">
<div className="flex items-baseline flex-wrap lg:flex-nowrap gap-2.5"> <div className="flex items-baseline flex-wrap lg:flex-nowrap gap-2.5">
<label className="form-label flex items-center gap-1 max-w-56"> <label className="form-label flex items-center gap-1 max-w-56">
Transaction Type Id<span className="text-red-500">*</span> Transaction Type<span className="text-red-500">*</span>
</label> </label>
<Select <Select
value={formField.transaction_type} value={formField.transaction_type}
@ -361,7 +370,12 @@ const AddDialog = () => {
<label className="form-label flex items-center gap-1 max-w-56"> <label className="form-label flex items-center gap-1 max-w-56">
Agent Name Agent Name
</label> </label>
<Input type="text" placeholder="Type Agent Only" readOnly className='cursor-not-allowed' /> <Input
type="text"
placeholder="Type Agent Only"
readOnly
className="cursor-not-allowed"
/>
</div> </div>
</div> </div>
)} )}
@ -370,7 +384,13 @@ const AddDialog = () => {
<Button type="button" variant="outline" onClick={resetForm}> <Button type="button" variant="outline" onClick={resetForm}>
Reset Reset
</Button> </Button>
<Button variant="default">Create</Button> <Button variant="default" type="submit" disabled={isSubmitting}>
{isSubmitting ? (
<RefreshCw className="animate-spin h-8 w-8 text-white mx-3" />
) : (
'Create'
)}
</Button>
</div> </div>
</div> </div>
</form> </form>

View File

@ -33,6 +33,7 @@ import {
CommandList CommandList
} from '@/components/ui/command'; } from '@/components/ui/command';
import { doSaveLogActivity } from '@/actions/GlobalActions'; import { doSaveLogActivity } from '@/actions/GlobalActions';
import { RefreshCw } from 'lucide-react';
const API_URL_CUSTOMER = apiConfig.service_customer; const API_URL_CUSTOMER = apiConfig.service_customer;
const API_URL_MASTERDATA = apiConfig.service_master_data; const API_URL_MASTERDATA = apiConfig.service_master_data;
@ -76,6 +77,7 @@ const EditDialog = () => {
const [formField, setFormField] = useState(initialState); const [formField, setFormField] = useState(initialState);
const [transactions, setTransactions] = useState<TransactionProps[]>([]); const [transactions, setTransactions] = useState<TransactionProps[]>([]);
const [customers, setCustomers] = useState<CustomerProps[]>([]); const [customers, setCustomers] = useState<CustomerProps[]>([]);
const [isSubmitting, setIsSubmitting] = useState(false);
const resetForm = () => { const resetForm = () => {
setFormField(initialState); setFormField(initialState);
@ -85,27 +87,34 @@ const EditDialog = () => {
const doUpdateProvider = useCallback( const doUpdateProvider = useCallback(
async (e: React.FormEvent<HTMLFormElement>) => { async (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault(); e.preventDefault();
setIsSubmitting(true);
const response = await PutData( try {
`${API_URL_MASTERDATA}/provider/update/${selectedProvider}`, const response = await PutData(
formField `${API_URL_MASTERDATA}/provider/update/${selectedProvider}`,
); formField
);
if (response?.status) { if (response?.status) {
resetForm(); resetForm();
handleEditDialog(false, null); handleEditDialog(false, null);
toast.success('Provider updated successfully.'); toast.success('Provider updated successfully.');
const createActivity = { const createActivity = {
module: 'Manage Provider', module: 'Manage Provider',
description: `Update Provider => ${selectedProvider}`, description: `Update Provider => ${selectedProvider}`,
action: 'U' action: 'U'
}; };
doSaveLogActivity(createActivity); doSaveLogActivity(createActivity);
reload(); reload();
} else { } else {
toast.error('Failed to update provider.'); toast.error('Failed to update provider.');
setAlert({ show: true, message: 'Failed to update provider.' }); setAlert({ show: true, message: response?.message });
}
} catch (error) {
toast.error('Something went wrong, please try again.');
} finally {
setIsSubmitting(false);
} }
}, },
[selectedProvider, formField] [selectedProvider, formField]
@ -319,7 +328,7 @@ const EditDialog = () => {
<div className="w-full"> <div className="w-full">
<div className="flex items-baseline flex-wrap lg:flex-nowrap gap-2.5"> <div className="flex items-baseline flex-wrap lg:flex-nowrap gap-2.5">
<label className="form-label flex items-center gap-1 max-w-56"> <label className="form-label flex items-center gap-1 max-w-56">
Transaction Type Id<span className="text-red-500">*</span> Transaction Type<span className="text-red-500">*</span>
</label> </label>
<Select <Select
value={formField.transaction_type} value={formField.transaction_type}
@ -409,7 +418,13 @@ const EditDialog = () => {
)} )}
<div className="flex justify-end"> <div className="flex justify-end">
<Button variant="default">Save Changes</Button> <Button variant="default" type="submit" disabled={isSubmitting}>
{isSubmitting ? (
<RefreshCw className="animate-spin h-8 w-8 text-white mx-3" />
) : (
'Save Changes'
)}
</Button>
</div> </div>
</div> </div>
</form> </form>

View File

@ -24,6 +24,7 @@ import {
SelectValue SelectValue
} from '@/components/ui/select'; } from '@/components/ui/select';
import { doSaveLogActivity } from '@/actions/GlobalActions'; import { doSaveLogActivity } from '@/actions/GlobalActions';
import { RefreshCw } from 'lucide-react';
const API_URL = apiConfig.service_master_data; const API_URL = apiConfig.service_master_data;
@ -48,6 +49,7 @@ const AddDialog = () => {
}; };
const [formField, setFormField] = useState(initialState); const [formField, setFormField] = useState(initialState);
const [isSubmitting, setIsSubmitting] = useState(false);
const created_time = new Date(); const created_time = new Date();
const formattedTime = created_time.toISOString().slice(0, 19).replace('T', ' '); const formattedTime = created_time.toISOString().slice(0, 19).replace('T', ' ');
@ -68,24 +70,31 @@ const AddDialog = () => {
const doCreateReward = useCallback( const doCreateReward = useCallback(
async (e: React.FormEvent<HTMLFormElement>) => { async (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault(); e.preventDefault();
// console.log('Data yang akan dikirim:', formField); setIsSubmitting(true);
const response = await PostData(`${API_URL}/reward/create`, formField);
if (response?.status) { try {
handleAddDialog(false); const response = await PostData(`${API_URL}/reward/create`, formField);
resetForm();
reload();
toast.success('Reward Create successfully!');
const createActivity = {
module: 'Manage Reward',
description: `Create New Reward => ${formField.name}`,
action: 'C'
};
doSaveLogActivity(createActivity); if (response?.status) {
} else { handleAddDialog(false);
toast.error('Failed to create reward.'); resetForm();
setAlert({ show: true, message: 'Failed to create reward. Please try again.' }); reload();
toast.success('Reward Create successfully!');
const createActivity = {
module: 'Manage Reward',
description: `Create New Reward => ${formField.name}`,
action: 'C'
};
doSaveLogActivity(createActivity);
} else {
toast.error('Failed to create reward.');
setAlert({ show: true, message: response?.message });
}
} catch (error) {
toast.error('Something went wrong, please try again.');
} finally {
setIsSubmitting(false);
} }
}, },
[formField] [formField]
@ -139,7 +148,7 @@ const AddDialog = () => {
<div className="card-body grid gap-5"> <div className="card-body grid gap-5">
<div className="grid grid-cols-8 gap-2 w-full items-center"> <div className="grid grid-cols-8 gap-2 w-full items-center">
<label className="form-label flex items-center gap-1 col-span-2"> <label className="form-label flex items-center gap-1 col-span-2">
Name<span className="text-red-500">*</span> Reward Name<span className="text-red-500">*</span>
</label> </label>
<Input <Input
@ -154,7 +163,7 @@ const AddDialog = () => {
</div> </div>
<div className="grid grid-cols-8 gap-2 w-full items-center"> <div className="grid grid-cols-8 gap-2 w-full items-center">
<label className="form-label flex items-center gap-1 col-span-2"> <label className="form-label flex items-center gap-1 col-span-2">
Type<span className="text-red-500">*</span> Reward Type<span className="text-red-500">*</span>
</label> </label>
<div className="col-span-6"> <div className="col-span-6">
@ -223,8 +232,12 @@ const AddDialog = () => {
<Button type="button" variant="outline" onClick={resetForm}> <Button type="button" variant="outline" onClick={resetForm}>
Reset Reset
</Button> </Button>
<Button variant="default" type="submit"> <Button variant="default" type="submit" disabled={isSubmitting}>
Save Change {isSubmitting ? (
<RefreshCw className="animate-spin h-8 w-8 text-white mx-3" />
) : (
'Create'
)}
</Button> </Button>
</div> </div>
</div> </div>

View File

@ -24,6 +24,7 @@ import {
} from '@/components/ui/select'; } from '@/components/ui/select';
import { useManageRewardContext } from '../hooks/useManageRewardContext'; import { useManageRewardContext } from '../hooks/useManageRewardContext';
import { doSaveLogActivity } from '@/actions/GlobalActions'; import { doSaveLogActivity } from '@/actions/GlobalActions';
import { RefreshCw } from 'lucide-react';
const API_URL = apiConfig.service_master_data; const API_URL = apiConfig.service_master_data;
@ -34,6 +35,7 @@ const EditDialog = () => {
const { PutData, GetData } = useCallApi(); const { PutData, GetData } = useCallApi();
const parsedUser = getAuth()?.user; const parsedUser = getAuth()?.user;
const [isLoading, setIsLoading] = useState(false); const [isLoading, setIsLoading] = useState(false);
const [isSubmitting, setIsSubmitting] = useState(false);
const [alert, setAlert] = useState({ const [alert, setAlert] = useState({
show: false, show: false,
message: '' message: ''
@ -69,25 +71,31 @@ const EditDialog = () => {
const doUpdateReward = useCallback( const doUpdateReward = useCallback(
async (e: React.FormEvent<HTMLFormElement>) => { async (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault(); e.preventDefault();
setIsSubmitting(true);
// console.log('Ini datanya:', selectedReward); try {
const response = await PutData(`${API_URL}/reward/update/${selectedReward}`, formField); const response = await PutData(`${API_URL}/reward/update/${selectedReward}`, formField);
if (response?.status) { if (response?.status) {
resetForm(); resetForm();
handleEditDialog(false, null); handleEditDialog(false, null);
toast.success('Success Update Reward'); toast.success('Success Update Reward');
reload(); reload();
const editActivity = { const editActivity = {
module: 'Manage Reward', module: 'Manage Reward',
description: `Edit Reward => ${formField.name}`, description: `Edit Reward => ${formField.name}`,
action: 'U' action: 'U'
}; };
doSaveLogActivity(editActivity); doSaveLogActivity(editActivity);
} else { } else {
toast.error('Error Update Reward'); toast.error('Error Update Reward');
setAlert({ show: true, message: 'Failed to Update Reward. Please try again.' }); setAlert({ show: true, message: response?.message });
}
} catch (error) {
toast.error('Something went wrong, please try again.');
} finally {
setIsSubmitting(false);
} }
}, },
[selectedReward, formField] [selectedReward, formField]
@ -181,7 +189,7 @@ const EditDialog = () => {
<div className="card-body grid gap-5"> <div className="card-body grid gap-5">
<div className="grid grid-cols-8 gap-2 w-full items-center"> <div className="grid grid-cols-8 gap-2 w-full items-center">
<label className="form-label flex items-center gap-1 col-span-2"> <label className="form-label flex items-center gap-1 col-span-2">
Name<span className="text-red-500">*</span> Reward Name<span className="text-red-500">*</span>
</label> </label>
<Input <Input
@ -193,7 +201,7 @@ const EditDialog = () => {
</div> </div>
<div className="grid grid-cols-8 gap-2 w-full items-center"> <div className="grid grid-cols-8 gap-2 w-full items-center">
<label className="form-label flex items-center gap-1 col-span-2"> <label className="form-label flex items-center gap-1 col-span-2">
Type<span className="text-red-500">*</span> Reward Type<span className="text-red-500">*</span>
</label> </label>
<div className="col-span-6"> <div className="col-span-6">
@ -261,7 +269,13 @@ const EditDialog = () => {
</div> </div>
</div> </div>
<div className="flex justify-end gap-5"> <div className="flex justify-end gap-5">
<Button variant="default">Save Changes</Button> <Button variant="default" type="submit" disabled={isSubmitting}>
{isSubmitting ? (
<RefreshCw className="animate-spin h-8 w-8 text-white mx-7" />
) : (
'Save Changes'
)}
</Button>
</div> </div>
</div> </div>
</form> </form>

View File

@ -25,6 +25,7 @@ import {
CommandList CommandList
} from '@/components/ui/command'; } from '@/components/ui/command';
import { doSaveLogActivity } from '@/actions/GlobalActions'; import { doSaveLogActivity } from '@/actions/GlobalActions';
import { RefreshCw } from 'lucide-react';
interface PostoAdmsProps { interface PostoAdmsProps {
PostoAdms_id: number; PostoAdms_id: number;
@ -40,6 +41,7 @@ const AddDialog = () => {
const parsedUser = getAuth()?.user; const parsedUser = getAuth()?.user;
const [posto_adms, setPostoadms] = useState<PostoAdmsProps[]>([]); const [posto_adms, setPostoadms] = useState<PostoAdmsProps[]>([]);
const [open, setOpen] = useState(false); const [open, setOpen] = useState(false);
const [isSubmitting, setIsSubmitting] = useState(false);
const [alert, setAlert] = useState({ const [alert, setAlert] = useState({
show: false, show: false,
message: '' message: ''
@ -63,23 +65,31 @@ const AddDialog = () => {
const doCreateSucos = useCallback( const doCreateSucos = useCallback(
async (e: React.FormEvent<HTMLFormElement>) => { async (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault(); e.preventDefault();
const response = await PostData(`${API_URL}/sucos/create`, formField); setIsSubmitting(true);
if (response?.status) { try {
resetForm(); const response = await PostData(`${API_URL}/sucos/create`, formField);
handleAddDialog(false);
reload();
toast.success('Sucos created successfully!');
const createActivity = {
module: 'Manage Sucos',
description: `Create Sucos => ${formField.name}`,
action: 'C'
};
doSaveLogActivity(createActivity); if (response?.status) {
} else { resetForm();
toast.error('Failed to create Sucos Please try again.'); handleAddDialog(false);
setAlert({ show: true, message: 'Failed to create Sucos Please try again.' }); reload();
toast.success('Sucos created successfully!');
const createActivity = {
module: 'Manage Sucos',
description: `Create Sucos => ${formField.name}`,
action: 'C'
};
doSaveLogActivity(createActivity);
} else {
toast.error('Failed to create Sucos Please try again.');
setAlert({ show: true, message: response?.message });
}
} catch (error) {
toast.error('Something went wrong. Please try again.');
} finally {
setIsSubmitting(false);
} }
}, },
[formField] [formField]
@ -225,7 +235,13 @@ const AddDialog = () => {
<Button type="button" variant="outline" onClick={resetForm}> <Button type="button" variant="outline" onClick={resetForm}>
Reset Reset
</Button> </Button>
<Button variant="default">Save Changes</Button> <Button variant="default" type="submit" disabled={isSubmitting}>
{isSubmitting ? (
<RefreshCw className="animate-spin h-8 w-8 text-white mx-3" />
) : (
'Create'
)}
</Button>
</div> </div>
</div> </div>
</form> </form>

View File

@ -25,6 +25,7 @@ import {
CommandList CommandList
} from '@/components/ui/command'; } from '@/components/ui/command';
import { doSaveLogActivity } from '@/actions/GlobalActions'; import { doSaveLogActivity } from '@/actions/GlobalActions';
import { RefreshCw } from 'lucide-react';
interface PostoAdmsProps { interface PostoAdmsProps {
PostoAdms_id: number; // Ubah ke PostoAdms_id PostoAdms_id: number; // Ubah ke PostoAdms_id
@ -39,6 +40,7 @@ const EditDialog = () => {
const { PutData, GetData } = useCallApi(); const { PutData, GetData } = useCallApi();
const parsedUser = getAuth()?.user; const parsedUser = getAuth()?.user;
const [open, setOpen] = useState(false); const [open, setOpen] = useState(false);
const [isSubmitting, setIsSubmitting] = useState(false);
const [isLoading, setIsLoading] = useState(false); const [isLoading, setIsLoading] = useState(false);
const [postoadms, setPostoadms] = useState<PostoAdmsProps[]>([]); const [postoadms, setPostoadms] = useState<PostoAdmsProps[]>([]);
@ -69,24 +71,31 @@ const EditDialog = () => {
const doUpdateSucos = useCallback( const doUpdateSucos = useCallback(
async (e: React.FormEvent<HTMLFormElement>) => { async (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault(); e.preventDefault();
setIsSubmitting(true);
const response = await PutData(`${API_URL}/sucos/update/${selectedSucos}`, formField); try {
const response = await PutData(`${API_URL}/sucos/update/${selectedSucos}`, formField);
if (response?.status) { if (response?.status) {
resetForm(); resetForm();
handleEditDialog(false, null); handleEditDialog(false, null);
toast.success('Success Update Sucos'); toast.success('Success Update Sucos');
reload(); reload();
const createActivity = { const createActivity = {
module: 'Manage Sucos', module: 'Manage Sucos',
description: `Edit Sucos => ${selectedSucos}`, description: `Edit Sucos => ${selectedSucos}`,
action: 'U' action: 'U'
}; };
doSaveLogActivity(createActivity); doSaveLogActivity(createActivity);
} else { } else {
toast.error('Failed Update Sucos'); toast.error('Failed Update Sucos');
setAlert({ show: true, message: 'Failed Update Sucos. Please try again' }); setAlert({ show: true, message: response?.message });
}
} catch (error) {
toast.error('Something went wrong, please try again.');
} finally {
setIsSubmitting(false);
} }
}, },
[selectedSucos, formField] [selectedSucos, formField]
@ -260,7 +269,13 @@ const EditDialog = () => {
</div> </div>
<div className="flex justify-end gap-5"> <div className="flex justify-end gap-5">
<Button className="btn btn-primary">Save Changes</Button> <Button variant="default" type="submit" disabled={isSubmitting}>
{isSubmitting ? (
<RefreshCw className="animate-spin h-8 w-8 text-white mx-7" />
) : (
'Save Changes'
)}
</Button>
</div> </div>
</div> </div>
</form> </form>

View File

@ -23,6 +23,7 @@ import {
import { Button } from '@/components/ui/button'; import { Button } from '@/components/ui/button';
import { Checkbox } from '@/components/ui/checkbox'; import { Checkbox } from '@/components/ui/checkbox';
import { doSaveLogActivity } from '@/actions/GlobalActions'; import { doSaveLogActivity } from '@/actions/GlobalActions';
import { RefreshCw } from 'lucide-react';
interface CurrencyProps { interface CurrencyProps {
ID: string; ID: string;
@ -64,6 +65,7 @@ const AddDialog = () => {
id_currency: '' id_currency: ''
}; };
const [formField, setFormField] = useState(initialState); const [formField, setFormField] = useState(initialState);
const [isSubmitting, setIsSubmitting] = useState(false);
const [currencies, setCurrencies] = useState<CurrencyProps[]>([]); const [currencies, setCurrencies] = useState<CurrencyProps[]>([]);
const [groups, setGroups] = useState<GroupProps[]>([]); const [groups, setGroups] = useState<GroupProps[]>([]);
@ -95,24 +97,31 @@ const AddDialog = () => {
const doCreateWallet = useCallback( const doCreateWallet = useCallback(
async (e: React.FormEvent<HTMLFormElement>) => { async (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault(); e.preventDefault();
setIsSubmitting(true);
const response = await PostData(`${API_URL_MASTER_DATA}/wallet/create`, formField); try {
const response = await PostData(`${API_URL_MASTER_DATA}/wallet/create`, formField);
if (response?.status) { if (response?.status) {
handleAddDialog(false); handleAddDialog(false);
toast.success('Success Create Wallet'); toast.success('Success Create Wallet');
reload(); reload();
const createActivity = { const createActivity = {
module: 'Manage Wallet', module: 'Manage Wallet',
description: `Create Wallet => ${formField.name}`, description: `Create Wallet => ${formField.name}`,
action: 'C' action: 'C'
}; };
doSaveLogActivity(createActivity); doSaveLogActivity(createActivity);
} else { } else {
toast.error('Failed Create Wallet'); toast.error('Failed Create Wallet');
setAlert({ show: true, message: 'Failed Create Wallet' }); setAlert({ show: true, message: response?.message });
}
} catch (error) {
toast.error('Something went wrong, please try again.');
} finally {
setIsSubmitting(false);
} }
}, },
[formField] [formField]
@ -293,7 +302,13 @@ const AddDialog = () => {
<Button type="button" variant="outline" onClick={resetForm}> <Button type="button" variant="outline" onClick={resetForm}>
Reset Reset
</Button> </Button>
<Button variant="default">Create</Button> <Button variant="default" type="submit" disabled={isSubmitting}>
{isSubmitting ? (
<RefreshCw className="animate-spin h-8 w-8 text-white mx-3" />
) : (
'Create'
)}
</Button>
</div> </div>
</div> </div>
</form> </form>

View File

@ -22,6 +22,7 @@ import {
} from '@/components/ui/select'; } from '@/components/ui/select';
import { Button } from '@/components/ui/button'; import { Button } from '@/components/ui/button';
import { doSaveLogActivity } from '@/actions/GlobalActions'; import { doSaveLogActivity } from '@/actions/GlobalActions';
import { RefreshCw } from 'lucide-react';
interface CurrencyProps { interface CurrencyProps {
ID: string; ID: string;
@ -66,6 +67,7 @@ const EditDialog = () => {
const [formField, setFormField] = useState(initialState); const [formField, setFormField] = useState(initialState);
const [currencies, setCurrencies] = useState<CurrencyProps[]>([]); const [currencies, setCurrencies] = useState<CurrencyProps[]>([]);
const [groups, setGroups] = useState<GroupProps[]>([]); const [groups, setGroups] = useState<GroupProps[]>([]);
const [isSubmitting, setIsSubmitting] = useState(false);
const resetForm = () => { const resetForm = () => {
setFormField(initialState); setFormField(initialState);
@ -75,27 +77,34 @@ const EditDialog = () => {
const doUpdateWallet = useCallback( const doUpdateWallet = useCallback(
async (payload: { name: string; description: string; status: string }) => { async (payload: { name: string; description: string; status: string }) => {
// e.preventDefault(); // e.preventDefault();
setIsSubmitting(true);
const response = await PutData( try {
`${API_URL_MASTER_DATA}/wallet/update/${selectedWallet?.id}`, const response = await PutData(
payload `${API_URL_MASTER_DATA}/wallet/update/${selectedWallet?.id}`,
); payload
);
if (response?.status) { if (response?.status) {
handleEditDialog(false, null); handleEditDialog(false, null);
toast.success('Success Update Wallet'); toast.success('Success Update Wallet');
reload(); reload();
const createActivity = { const createActivity = {
module: 'Manage Wallet', module: 'Manage Wallet',
description: `Edit Wallet => ${selectedWallet?.id} - ${selectedWallet?.name}`, description: `Edit Wallet => ${selectedWallet?.id} - ${selectedWallet?.name}`,
action: 'U' action: 'U'
}; };
doSaveLogActivity(createActivity); doSaveLogActivity(createActivity);
} else { } else {
toast.error('Failed Update Wallet'); toast.error('Failed Update Wallet');
setAlert({ show: true, message: 'Failed Update Wallet' }); setAlert({ show: true, message: response?.message });
}
} catch (error) {
toast.error('Something went wrong, please try again.');
} finally {
setIsSubmitting(false);
} }
}, },
[formField] [formField]
@ -314,8 +323,12 @@ const EditDialog = () => {
</div> </div>
<div className="flex justify-end gap-5"> <div className="flex justify-end gap-5">
<Button variant="default" type="submit"> <Button variant="default" type="submit" disabled={isSubmitting}>
Update {isSubmitting ? (
<RefreshCw className="animate-spin h-8 w-8 text-white mx-7" />
) : (
'Save Changes'
)}
</Button> </Button>
</div> </div>
</div> </div>

View File

@ -32,6 +32,7 @@ import {
} from '@/components/ui/command'; } from '@/components/ui/command';
import { NumericFormat } from 'react-number-format'; import { NumericFormat } from 'react-number-format';
import { doSaveLogActivity } from '@/actions/GlobalActions'; import { doSaveLogActivity } from '@/actions/GlobalActions';
import { RefreshCw } from 'lucide-react';
interface GroupProps { interface GroupProps {
ID: string; ID: string;
@ -88,6 +89,7 @@ const AddDialog = () => {
}; };
const [formField, setFormField] = useState(initialState); const [formField, setFormField] = useState(initialState);
const [wallets, setWallets] = useState<WalletProps[]>([]); const [wallets, setWallets] = useState<WalletProps[]>([]);
const [isSubmitting, setIsSubmitting] = useState(false);
const resetForm = () => { const resetForm = () => {
setFormField(initialState); setFormField(initialState);
@ -97,24 +99,31 @@ const AddDialog = () => {
const doCreateWalletRule = useCallback( const doCreateWalletRule = useCallback(
async (e: React.FormEvent<HTMLFormElement>) => { async (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault(); e.preventDefault();
setIsSubmitting(true);
const response = await PostData(`${API_URL_WALLET}/dashboard/wallet_rule`, formField); try {
const response = await PostData(`${API_URL_WALLET}/dashboard/wallet_rule`, formField);
if (response?.status) { if (response?.status) {
handleAddDialog(false); handleAddDialog(false);
toast.success('Success Create Wallet Rule'); toast.success('Success Create Wallet Rule');
reload(); reload();
const createActivity = { const createActivity = {
module: 'Manage Wallet Rule', module: 'Manage Wallet Rule',
description: `Create Wallet Rule => ${selectedWalletRule?.ID}`, description: `Create Wallet Rule => ${selectedWalletRule?.ID}`,
action: 'C' action: 'C'
}; };
doSaveLogActivity(createActivity); doSaveLogActivity(createActivity);
} else { } else {
toast.error('Failed Create Wallet Rule'); toast.error('Failed Create Wallet Rule');
setAlert({ show: true, message: 'Failed Create Wallet Rule' }); setAlert({ show: true, message: response?.message });
}
} catch (error) {
toast.error('Something went wrong, please try again.');
} finally {
setIsSubmitting(false);
} }
}, },
[formField] [formField]
@ -377,7 +386,13 @@ const AddDialog = () => {
<Button type="button" variant="outline" onClick={resetForm}> <Button type="button" variant="outline" onClick={resetForm}>
Reset Reset
</Button> </Button>
<Button variant="default">Create</Button> <Button variant="default" type="submit" disabled={isSubmitting}>
{isSubmitting ? (
<RefreshCw className="animate-spin h-8 w-8 text-white mx-3" />
) : (
'Create'
)}
</Button>
</div> </div>
</div> </div>
</form> </form>

View File

@ -32,6 +32,7 @@ import { Input } from '@/components/ui/input';
import { Button } from '@/components/ui/button'; import { Button } from '@/components/ui/button';
import { NumericFormat } from 'react-number-format'; import { NumericFormat } from 'react-number-format';
import { doSaveLogActivity } from '@/actions/GlobalActions'; import { doSaveLogActivity } from '@/actions/GlobalActions';
import { RefreshCw } from 'lucide-react';
interface GroupProps { interface GroupProps {
ID: string; ID: string;
@ -79,6 +80,7 @@ const EditDialog = () => {
const [formField, setFormField] = useState(initialState); const [formField, setFormField] = useState(initialState);
const [groups, setGroups] = useState<GroupProps[]>([]); const [groups, setGroups] = useState<GroupProps[]>([]);
const [wallets, setWallets] = useState<WalletProps[]>([]); const [wallets, setWallets] = useState<WalletProps[]>([]);
const [isSubmitting, setIsSubmitting] = useState(false);
const resetForm = () => { const resetForm = () => {
setFormField(initialState); setFormField(initialState);
@ -88,27 +90,34 @@ const EditDialog = () => {
const doUpdateWalletRule = useCallback( const doUpdateWalletRule = useCallback(
async (e: React.FormEvent<HTMLFormElement>) => { async (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault(); e.preventDefault();
setIsSubmitting(true);
const response = await PutData( try {
`${API_URL_WALLET}/dashboard/wallet_rule/${selectedWalletRule?.ID}`, const response = await PutData(
formField `${API_URL_WALLET}/dashboard/wallet_rule/${selectedWalletRule?.ID}`,
); formField
);
if (response?.status) { if (response?.status) {
handleEditDialog(false, null); handleEditDialog(false, null);
toast.success('Success Update Wallet Rule'); toast.success('Success Update Wallet Rule');
reload(); reload();
const createActivity = { const createActivity = {
module: 'Manage Wallet Rule', module: 'Manage Wallet Rule',
description: `Edit Wallet Rule => ${selectedWalletRule?.ID}`, description: `Edit Wallet Rule => ${selectedWalletRule?.ID}`,
action: 'U' action: 'U'
}; };
doSaveLogActivity(createActivity); doSaveLogActivity(createActivity);
} else { } else {
toast.error('Failed Update Wallet Rule'); toast.error('Failed Update Wallet Rule');
setAlert({ show: true, message: 'Failed Update Wallet Rule' }); setAlert({ show: true, message: response?.message });
}
} catch (error) {
toast.error('Something went wrong, please try again');
} finally {
setIsSubmitting(false);
} }
}, },
[formField] [formField]
@ -402,7 +411,13 @@ const EditDialog = () => {
</div> </div>
<div className="flex justify-end gap-5"> <div className="flex justify-end gap-5">
<Button variant="default">Update</Button> <Button variant="default" type="submit" disabled={isSubmitting}>
{isSubmitting ? (
<RefreshCw className="animate-spin h-8 w-8 text-white mx-7" />
) : (
'Save Changes'
)}
</Button>
</div> </div>
</div> </div>
</form> </form>

View File

@ -22,6 +22,7 @@ import {
SelectValue SelectValue
} from '@/components/ui/select'; } from '@/components/ui/select';
import { doSaveLogActivity } from '@/actions/GlobalActions'; import { doSaveLogActivity } from '@/actions/GlobalActions';
import { RefreshCw } from 'lucide-react';
const API_URL = apiConfig.service_dashboard; const API_URL = apiConfig.service_dashboard;
const AddDialog = () => { const AddDialog = () => {
@ -43,9 +44,11 @@ const AddDialog = () => {
status: '' status: ''
}; };
const [formField, setFormField] = useState(initialState); const [formField, setFormField] = useState(initialState);
const [isSubmitting, setIsSubmitting] = useState(false);
const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => { const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault(); e.preventDefault();
setIsSubmitting(true);
if ( if (
formField.module === '' || formField.module === '' ||
@ -58,28 +61,31 @@ const AddDialog = () => {
return; return;
} }
// console.log('Data dikirim ke API:', formField); try {
const response = await PostData(`${API_URL}/menus/create`, formField); const response = await PostData(`${API_URL}/menus/create`, formField);
// console.log('Response from API:', response); if (response?.status) {
handleAddDialog(false);
resetForm();
toast.success('Success Create Menu');
const createActivity = {
module: 'Manage Menu',
description: `Create Menu => ${selectedMenu}`,
action: 'C'
};
if (response?.status) { doSaveLogActivity(createActivity);
handleAddDialog(false); reload();
resetForm(); } else {
toast.success('Success Create Menu'); toast.error('Failed Create Menu');
const createActivity = { setAlert({ show: true, message: response?.message });
module: 'Manage Menu', }
description: `Create Menu => ${selectedMenu}`, } catch (error) {
action: 'C' toast.error('Something went wrong, please try again');
}; } finally {
setIsSubmitting(false);
doSaveLogActivity(createActivity);
reload();
} else {
toast.error('Failed Create Menu');
setAlert({ show: true, message: 'Failed Create Menu' });
} }
// console.log(formField);
setAlert({ show: false, message: '' }); setAlert({ show: false, message: '' });
}; };
@ -226,7 +232,13 @@ const AddDialog = () => {
<Button type="button" variant="outline" onClick={resetForm}> <Button type="button" variant="outline" onClick={resetForm}>
Reset Reset
</Button> </Button>
<Button variant="default">Save Changes</Button> <Button variant="default" type="submit" disabled={isSubmitting}>
{isSubmitting ? (
<RefreshCw className="animate-spin h-8 w-8 text-white mx-3" />
) : (
'Create'
)}
</Button>
</div> </div>
</div> </div>
</form> </form>

View File

@ -32,6 +32,7 @@ const EditDialog = () => {
const { reload } = useDataGrid(); const { reload } = useDataGrid();
const { PutData } = useCallApi(); const { PutData } = useCallApi();
const [open, setOpen] = useState(false); const [open, setOpen] = useState(false);
const [isSubmitting, setIsSubmitting] = useState(false);
const [alert, setAlert] = useState({ const [alert, setAlert] = useState({
show: false, show: false,
message: '' message: ''
@ -49,6 +50,7 @@ const EditDialog = () => {
const handleUpdate = async (e: React.FormEvent<HTMLFormElement>) => { const handleUpdate = async (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault(); e.preventDefault();
setIsSubmitting(true);
if ( if (
selectedMenu.module === '' || selectedMenu.module === '' ||
@ -62,26 +64,33 @@ const EditDialog = () => {
return; return;
} }
const updateMenu = selectedMenu; try {
if (updateMenu.id_parent === null) updateMenu.id_parent = ''; const updateMenu = selectedMenu;
delete updateMenu.parentName; if (updateMenu.id_parent === null) updateMenu.id_parent = '';
const response = await PutData(`${API_URL}/menus/update/${selectedMenu.id}`, selectedMenu); delete updateMenu.parentName;
if (response?.status) { const response = await PutData(`${API_URL}/menus/update/${selectedMenu.id}`, selectedMenu);
handleEditDialog(false, null); if (response?.status) {
resetForm(); handleEditDialog(false, null);
toast.success('Success Update Menu'); resetForm();
const createActivity = { toast.success('Success Update Menu');
module: 'Manage Menu', const createActivity = {
description: `Update Menu => ${selectedMenu.name}`, module: 'Manage Menu',
action: 'U' description: `Update Menu => ${selectedMenu.name}`,
}; action: 'U'
};
doSaveLogActivity(createActivity); doSaveLogActivity(createActivity);
reload(); reload();
} else { } else {
toast.error('Failed Update Menu'); toast.error('Failed Update Menu');
setAlert({ show: true, message: 'Failed Update Menu' }); setAlert({ show: true, message: response?.message });
}
} catch (error) {
toast.error('Something went wrong, please trt again.');
} finally {
setIsSubmitting(false);
} }
setAlert({ show: false, message: '' }); setAlert({ show: false, message: '' });
}; };

View File

@ -2,7 +2,6 @@ import { Container, DataGridInner } from '@/components';
import { TransactionProvider } from './hooks/TransactionContext'; import { TransactionProvider } from './hooks/TransactionContext';
import { Breadcrumbs, Link } from '@mui/material'; import { Breadcrumbs, Link } from '@mui/material';
import { Helmet } from 'react-helmet'; import { Helmet } from 'react-helmet';
import ResendTransaction from './blocks/ResendTransaction';
const Transaction = () => { const Transaction = () => {
return ( return (
@ -29,7 +28,6 @@ const Transaction = () => {
<div className="grid gap-5 lg:gap-7.5"> <div className="grid gap-5 lg:gap-7.5">
<DataGridInner /> <DataGridInner />
</div> </div>
{/* <ResendTransaction /> */}
</Container> </Container>
</TransactionProvider> </TransactionProvider>
</> </>

View File

@ -12,11 +12,13 @@ import {
DialogHeader, DialogHeader,
DialogTitle DialogTitle
} from '@/components/ui/dialog'; } from '@/components/ui/dialog';
import { useDataGrid } from '@/components';
const API_URL = apiConfig.transaction; const API_URL = apiConfig.transaction;
const DetailTransaction = () => { const DetailTransaction = () => {
const { GetData } = useCallApi(); const { GetData } = useCallApi();
// const { reload } = useDataGrid();
const { const {
showDetailDialog, showDetailDialog,
setShowDetailDialog, setShowDetailDialog,

View File

@ -11,7 +11,6 @@ import {
DialogHeader, DialogHeader,
DialogTitle DialogTitle
} from '@/components/ui/dialog'; } from '@/components/ui/dialog';
import { Button } from '@/components/ui/button';
import { Alert, useDataGrid } from '@/components'; import { Alert, useDataGrid } from '@/components';
import { doSaveLogActivity } from '@/actions/GlobalActions'; import { doSaveLogActivity } from '@/actions/GlobalActions';
import { toast } from 'sonner'; import { toast } from 'sonner';
@ -27,10 +26,14 @@ interface ResendTransactionProps {
const ResendTransaction = ({ isOpen, onClose, selectedTransactionForResend }: ResendTransactionProps) => { const ResendTransaction = ({ isOpen, onClose, selectedTransactionForResend }: ResendTransactionProps) => {
// const { showResendDialog, handleResendDialog, selectedTransactionForResend } = useTransactionContext(); // const { showResendDialog, handleResendDialog, selectedTransactionForResend } = useTransactionContext();
const { GetData, PostData } = useCallApi(); const { GetData, PostData } = useCallApi();
// const { reload } = useDataGrid(); const {
showDetailDialog,
setShowDetailDialog,
selectedTransactionId
} = useTransactionContext();
const { reload } = useDataGrid();
const [transactionDetails, setTransactionDetails] = useState<any>(null); const [transactionDetails, setTransactionDetails] = useState<any>(null);
const [alert, setAlert] = useState({ const [alert, setAlert] = useState({
show: false, show: false,
@ -137,13 +140,19 @@ const ResendTransaction = ({ isOpen, onClose, selectedTransactionForResend }: Re
} }
break; break;
case 'P': case 'P':
let walletParam = "";
apiEndpoint = `${API_URL}/transaction/purchase`; apiEndpoint = `${API_URL}/transaction/purchase`;
if (data.origin_wallet.name === 'Emoney Account') {
walletParam = "emoney";
} else if (data.origin_wallet.name === 'Point Account') {
walletParam = "point";
}
apiJsonData = { apiJsonData = {
id_origin_customer: data.origin_customer.id, id_origin_customer: data.origin_customer.id,
code_product: "object purchase : masih null", code_product: data.purchase.code,
wallet: "emoney or point", wallet: walletParam,
destination_number: "parameter number", destination_number: "",
destination_amount: "parameter amount", destination_amount: String(data.purchase.amount),
pin: pintransactiion pin: pintransactiion
} }
break; break;
@ -159,25 +168,26 @@ const ResendTransaction = ({ isOpen, onClose, selectedTransactionForResend }: Re
if (response?.status) { if (response?.status) {
setAlert({ show: false, message: '' }); setAlert({ show: false, message: '' });
// handleResendDialog(false, null); // handleResendDialog(false, null);
onClose();
setShowDetailDialog(false);
reload();
toast.success('Success Retry Transaction'); toast.success('Success Retry Transaction');
// reload();
const createActivity = { const createActivity = {
module: 'History Transaction', module: 'History Transaction',
description: `Retry Transaction => ${selectedTransactionForResend}`, description: `Retry Transaction => ${data.code}`,
action: 'U' action: 'U'
}; };
doSaveLogActivity(createActivity); doSaveLogActivity(createActivity);
} else { } else {
setAlert({ show: true, message: response?.message }); setAlert({ show: true, message: response?.message.message });
toast.error('Failed Retry Transaction'); toast.error('Failed Retry Transaction');
} }
}, [selectedTransactionForResend, PostData]); }, [selectedTransactionForResend, PostData]);
if (!isOpen) return null; if (!isOpen) return null;
return ( return (
<Dialog open={isOpen} onOpenChange={onClose}> <Dialog open={isOpen} onOpenChange={onClose}>
<DialogContent className="container-fixed max-w-md flex flex-col p-5 overflow-hidden [&>button]:hidden"> <DialogContent className="container-fixed max-w-md flex flex-col p-5 overflow-hidden [&>button]:hidden">

View File

@ -7,6 +7,7 @@ import { useCallApi } from '@/hooks';
import ListToolbar from '../blocks/ListToolbar'; import ListToolbar from '../blocks/ListToolbar';
import { useNavigate } from 'react-router'; import { useNavigate } from 'react-router';
import DetailTransaction from '../blocks/DetailTransaction'; import DetailTransaction from '../blocks/DetailTransaction';
import ResendTransaction from '../blocks/ResendTransaction';
interface TransactionProps { interface TransactionProps {
id: number; id: number;
@ -320,7 +321,7 @@ const TransactionProvider = ({ children }: { children: React.ReactNode }) => {
}} }}
> >
<Toaster expand visibleToasts={9} duration={3000} /> <Toaster expand visibleToasts={9} duration={3000} />
<DetailTransaction />
<DataGridProvider <DataGridProvider
columns={columns} columns={columns}
@ -333,6 +334,12 @@ const TransactionProvider = ({ children }: { children: React.ReactNode }) => {
getTransactionLists(pageIndex, pageSize, sorting, columnFilters) getTransactionLists(pageIndex, pageSize, sorting, columnFilters)
} }
> >
<DetailTransaction />
<ResendTransaction
isOpen={false}
onClose={() => console.log('Retry Transaction closed')}
selectedTransactionForResend={null}
/>
{children} {children}
</DataGridProvider> </DataGridProvider>
</ManageTransactionContext.Provider> </ManageTransactionContext.Provider>

View File

@ -474,6 +474,8 @@ const AddDialog = () => {
<SelectItem value="DE">Disbursment Escrow</SelectItem> <SelectItem value="DE">Disbursment Escrow</SelectItem>
<SelectItem value="DM">Disbursment Master Agent</SelectItem> <SelectItem value="DM">Disbursment Master Agent</SelectItem>
<SelectItem value="DA">Disbursment Agent</SelectItem> <SelectItem value="DA">Disbursment Agent</SelectItem>
<SelectItem value="WI">Withdraw Merchant</SelectItem>
<SelectItem value="IC">Income Merchant</SelectItem>
</SelectContent> </SelectContent>
</Select> </Select>
</div> </div>

View File

@ -608,6 +608,8 @@ const EditDialog = () => {
<SelectItem value="DE">Disbursment Escrow</SelectItem> <SelectItem value="DE">Disbursment Escrow</SelectItem>
<SelectItem value="DM">Disbursment Master Agent</SelectItem> <SelectItem value="DM">Disbursment Master Agent</SelectItem>
<SelectItem value="DA">Disbursment Agent</SelectItem> <SelectItem value="DA">Disbursment Agent</SelectItem>
<SelectItem value="WI">Withdraw Merchant</SelectItem>
<SelectItem value="IC">Income Merchant</SelectItem>
</SelectContent> </SelectContent>
</Select> </Select>
</div> </div>

View File

@ -189,7 +189,9 @@ const ManageTransferTypeContextProvider = ({ children }: { children: React.React
PL: 'Purchase Loja', PL: 'Purchase Loja',
DE: 'Disbursment Escrow', DE: 'Disbursment Escrow',
DM: 'Disbursment Master Agent', DM: 'Disbursment Master Agent',
DA: 'Disbursment Agent' DA: 'Disbursment Agent',
WI: 'Withdraw Merchant',
IC: 'Income Merchant'
}; };
return mapping[row.type] || 'Unknown'; return mapping[row.type] || 'Unknown';