Compare commits

..

7 Commits

Author SHA1 Message Date
victorAnumudu d131e981cf added recent payments 2025-10-16 19:51:22 +01:00
CHIEFSOFT\ameye 85a07427e5 fix text 2025-10-16 11:53:07 -04:00
CHIEFSOFT\ameye 647f9473a0 fix links 2025-10-14 03:06:21 -04:00
ameye 95ea5aaabf Merge branch 'rebuild-confirmation' of MERMS/MermsFirstOffice into master 2025-10-13 10:54:29 +00:00
victorAnumudu cb4b0e89c7 added rebuild confirmation modal 2025-10-13 06:50:00 +01:00
CHIEFSOFT\ameye b898f7c3e3 added office refreesh 2025-10-11 06:18:05 -04:00
ameye a5fc0890b4 Merge branch 'product-update-endpoint' of MERMS/MermsFirstOffice into master 2025-10-08 17:10:38 +00:00
12 changed files with 250 additions and 136 deletions
+1 -1
View File
@@ -66,7 +66,7 @@ export default function UserExist() {
navigate(RouteLinks.login, {replace:true})
}
}
if(userDetails.name){
if(userDetails?.email || userDetails?.username){
setPageIsLoading(false)
}else if(!userDetails.name && localStorage.getItem('token')){
loadUser(localStorage.getItem('token'))
@@ -71,7 +71,7 @@ export default function CustomerSubscriptionsView({subscriptions}) {
<br/>
<span className="badge badge-warning">
<a href={`https://${item?.external_url}`}
<a href={`${item?.external_url}`}
target='_blank'
rel="noreferrer">{item?.external_url}</a>
</span>
+1 -3
View File
@@ -45,9 +45,7 @@ export default function LoginCom() {
const {jwt_token, user} = res?.data
if (jwt_token) {
localStorage.setItem('token', jwt_token)
// localStorage.setItem('room', room)
const data = {jwt_token}
dispatch(updateUserDetails({...data, ...user}));
dispatch(updateUserDetails({jwt_token, ...user}));
}
setLoading(false)
navigate(RouteLinks.homePage, {state: {proceed: 'true'}}) // later add redux to dispatch state
+5 -2
View File
@@ -1,3 +1,4 @@
import { useSelector } from "react-redux";
import { LuSunDim } from "react-icons/lu";
import { IoMdSunny } from "react-icons/io";
@@ -17,6 +18,8 @@ export default function DashboardHeader() {
const {theme, handleTheme, setLogoutModal, activeMenu, handleActiveMenu, showAsideDrawer, setShowAsideDrawer} = GeneralLayoutContext()
const {userDetails:{username, email}} = useSelector((state) => state.userDetails) // GETS LOGGED IN USER
return (
<>
{/* HEADER SECTION*/}
@@ -60,8 +63,8 @@ export default function DashboardHeader() {
<div className="pop-modal z-[777] absolute p-4 w-52 sm:w-96 bg-white dark:bg-black-box right-0 top-16 rounded shadow-round_black dark:shadow-round_white">
<div className="w-full h-full flex flex-col gap-4">
<div className="flex flex-col text-black dark:text-white text-base sm:text-lg">
<h1 className="font-semibold">Username</h1>
<p className="-mt-2">username@gmail.com</p>
<h1 className="font-semibold">{username}</h1>
<p className="-mt-2">{email}</p>
</div>
<div className="rounded w-full flex justify-center items-center gap-2">
<MainBtn
+5 -2
View File
@@ -4,8 +4,9 @@ import DashboardHeader from './DashboardHeader'
import { GeneralLayoutContext } from '../../context/GeneralLayoutContext'
import DashboardAside from './aside/DashboardAside'
import RightAsideBar from './rightaside/RightAsideBar'
import { memo } from 'react'
export default function DashboardLayout() {
const DashboardLayout =memo(()=> {
// let {pathname} = useLocation()
@@ -54,4 +55,6 @@ export default function DashboardLayout() {
</>
</div>
)
}
})
export default DashboardLayout
@@ -1,22 +1,23 @@
import {useLocation} from 'react-router-dom'
import { useSelector } from "react-redux";
import RouteLinks from "../../../RouteLinks";
import DummyLogo from "../../DummyLogo";
import MainBtn from "../../MainBtn";
import AsideLink from "./AsideLink";
import AsideLinkWithSubLinks from "./AsideLinkWithSubLinks";
// import { useSelector } from "react-redux";
import {GeneralLayoutContext} from "../../../context/GeneralLayoutContext";
import {TbLogout2} from "react-icons/tb";
import UserAvatar from '../../../assets/user_avatar.jpg'
import Icons from "../../Icons";
export default function DashboardAside() {
const {pathname} = useLocation()
const {setLogoutModal, handleActiveMenu} = GeneralLayoutContext()
// const {userDetails} = useSelector((state) => state.userDetails) // GETS LOGGED IN USER ROLE DETAILS
const {userDetails:{username, email}} = useSelector((state) => state.userDetails) // GETS LOGGED IN USER
// const {role}= userDetails
return (
@@ -126,8 +127,8 @@ export default function DashboardAside() {
<div className="w-full min-h-48 flex flex-col justify-between gap-4">
<div className="w-full h-full">
<div className="flex flex-col text-black dark:text-white text-base sm:text-lg">
<h1 className="font-semibold">Username</h1>
<p className="-mt-2">username@gmail.com</p>
<h1 className="font-semibold">{username}</h1>
<p className="-mt-2">{email}</p>
</div>
</div>
<div className="rounded w-full flex items-center gap-2">
@@ -1,10 +1,16 @@
import React from 'react'
import {Link} from 'react-router-dom'
import Img from '../../../assets/user_avatar.jpg'
import CustomCounter from '../../CustomCounter'
import RouteLinks from '../../../RouteLinks'
export default function RecentPaymentsBar({data, isFetching, isError, error}) {
const recentPayment = data?.data?.recent_payment_summary
const recentLogin = data?.data?.recent_login
return (
<div className='h-full p-2 sm:p-4 large:p-8 flex flex-col gap-16 overflow-y-auto aside-scroll-design'>
<div className='h-full p-2 sm:p-4 large:p-8 flex flex-col gap-16 aside-scroll-design'>
<div className='flex flex-col gap-4'>
<p className='text-base text-white-body font-bold'>Recent Payments [7 days]</p>
{isFetching ?
@@ -18,32 +24,32 @@ export default function RecentPaymentsBar({data, isFetching, isError, error}) {
<div className='grid grid-cols-2 gap-4 sm:gap-6 large:gap-8'>
<div className='p-2 sm:p-3 large:p-4 flex flex-col border border-slate-500 border-dashed'>
<p className='text-base font-bold text-white-body'>
<CustomCounter targetNumber={18} timeInSeconds={1} />
<CustomCounter targetNumber={recentPayment?.approved} timeInSeconds={1} />
</p>
<p className='text-sm text-slate-500'>Approved</p>
</div>
<div className='p-2 sm:p-3 large:p-4 flex flex-col border border-slate-500 border-dashed'>
<p className='text-base font-bold text-white-body'>
<CustomCounter targetNumber={5} timeInSeconds={1} />
<CustomCounter targetNumber={recentPayment?.verified} timeInSeconds={1} />
</p>
<p className='text-sm text-slate-500'>Verified</p>
</div>
<div className='p-2 sm:p-3 large:p-4 flex flex-col border border-slate-500 border-dashed'>
<p className='text-base font-bold text-white-body'>
<CustomCounter targetNumber={1} timeInSeconds={1} />
<CustomCounter targetNumber={recentPayment?.failed} timeInSeconds={1} />
</p>
<p className='text-sm text-slate-500'>Failed</p>
</div>
<div className='p-2 sm:p-3 large:p-4 flex flex-col border border-slate-500 border-dashed'>
<p className='text-base font-bold text-white-body'>
<CustomCounter targetNumber={1} timeInSeconds={1} />
<CustomCounter targetNumber={recentPayment?.total} timeInSeconds={1} />
</p>
<p className='text-sm text-slate-500'>Total</p>
</div>
</div>
}
</div>
<div className='flex flex-col gap-4'>
<div className='overflow-y-auto h-full flex flex-col gap-4'>
<p className='text-base text-white-body font-bold'>Recent Login</p>
{isFetching ?
<div className='w-full flex justify-center'>
@@ -54,42 +60,22 @@ export default function RecentPaymentsBar({data, isFetching, isError, error}) {
<p className='text-base text-white-body font-bold'>{error?.message}</p>
:
<div className='flex flex-col gap-4'>
<div className='flex gap-3 items-center'>
<div className='px-4 py-2 bg-[#0E172E] rounded-md'>
<img src={Img} className='w-8' alt="Order" />
</div>
<div className='flex-col'>
<p className='text-base font-bold text-white-body'>Project Briefing</p>
<p className='text-sm text-slate-500'>Project Manager</p>
</div>
</div>
<div className='flex gap-3 items-center'>
<div className='px-4 py-2 bg-[#0E172E] rounded-md'>
<img src={Img} className='w-8' alt="Order" />
</div>
<div className='flex-col'>
<p className='text-base font-bold text-white-body'>Project Briefing</p>
<p className='text-sm text-slate-500'>Project Manager</p>
</div>
</div>
<div className='flex gap-3 items-center'>
<div className='px-4 py-2 bg-[#0E172E] rounded-md'>
<img src={Img} className='w-8' alt="Order" />
</div>
<div className='flex-col'>
<p className='text-base font-bold text-white-body'>Project Briefing</p>
<p className='text-sm text-slate-500'>Project Manager</p>
</div>
</div>
<div className='flex gap-3 items-center'>
<div className='px-4 py-2 bg-[#0E172E] rounded-md'>
<img src={Img} className='w-8' alt="Order" />
</div>
<div className='flex-col'>
<p className='text-base font-bold text-white-body'>Project Briefing</p>
<p className='text-sm text-slate-500'>Project Manager</p>
</div>
</div>
{recentLogin.map((item, index)=> {
if(index < 5){
return (
<div key={index} className='flex gap-3 items-center'>
<div className='px-4 py-2 bg-[#0E172E] rounded-md'>
<img src={Img} className='w-8' alt="Order" />
</div>
<div className='flex-col'>
<p className='text-base font-bold text-white-body'>{item.firstname} {item.lastname}</p>
<p className='text-sm text-slate-500'>{item.username}</p>
</div>
</div>
)
}
}
)}
</div>
}
</div>
@@ -29,14 +29,9 @@ export default function RightAsideBar() {
},
// staleTime: 0 //0 mins
})
const recentData = [] // RECENT LIST
// const recentData = data?.data // RECENT LIST
// const pagination = data?.data?.pagination
// console.log('RIGHT', data?.data)
return (
<div className='w-full h-full flex flex-col gap-8'>
<div className='w-full h-full pb-8 flex flex-col gap-8'>
{/* Menu */}
<div className='grid grid-cols-3 gap-8'>
<button name='orders' onClick={() => handleActiveMenu('orders')} className={`flex justify-center items-center px-2 py-3 large:px-4 large:py-5 rounded-md shadow-round_white bg-[#0E172E] text-white-body hover:scale-[1.1] ${active === 'orders' && 'scale-[1.2]'}`}>
@@ -51,9 +46,9 @@ export default function RightAsideBar() {
</div>
{/* Body */}
{active === 'orders' && <RecentPaymentsBar data={recentData} isFetching={isFetching} isError={isError} error={error} />}
{active === 'tickets' && <Tickets data={recentData} isFetching={isFetching} isError={isError} error={error} />}
{active === 'tasks' && <Tasks data={recentData} isFetching={isFetching} isError={isError} error={error} />}
{active === 'orders' && <RecentPaymentsBar data={data} isFetching={isFetching} isError={isError} error={error} />}
{active === 'tickets' && <Tickets data={data} isFetching={isFetching} isError={isError} error={error} />}
{active === 'tasks' && <Tasks data={data} isFetching={isFetching} isError={isError} error={error} />}
</div>
)
}
+10 -7
View File
@@ -3,6 +3,9 @@ import Img from '../../../assets/user_avatar.jpg'
import CustomCounter from '../../CustomCounter'
export default function Tickets({data, isFetching, isError, error}) {
const recentDeployment = data?.data?.recent_deployment_summary
return (
<div className='h-full p-2 sm:p-4 large:p-8 flex flex-col gap-16 overflow-y-auto aside-scroll-design'>
<div className='flex flex-col gap-4'>
@@ -18,27 +21,27 @@ export default function Tickets({data, isFetching, isError, error}) {
<div className='grid grid-cols-2 gap-4 sm:gap-6 large:gap-8'>
<div className='p-2 sm:p-3 large:p-4 flex flex-col border border-slate-500 border-dashed'>
<p className='text-base font-bold text-white-body'>
<CustomCounter targetNumber={18} timeInSeconds={1} />
<CustomCounter targetNumber={recentDeployment?.pending} timeInSeconds={1} />
</p>
<p className='text-sm text-slate-500'>Pending</p>
</div>
<div className='p-2 sm:p-3 large:p-4 flex flex-col border border-slate-500 border-dashed'>
<p className='text-base font-bold text-white-body'>
<CustomCounter targetNumber={2} timeInSeconds={1} />
<CustomCounter targetNumber={recentDeployment?.started} timeInSeconds={1} />
</p>
<p className='text-sm text-slate-500'>Offers</p>
<p className='text-sm text-slate-500'>Started</p>
</div>
<div className='p-2 sm:p-3 large:p-4 flex flex-col border border-slate-500 border-dashed'>
<p className='text-base font-bold text-white-body'>
<CustomCounter targetNumber={3} timeInSeconds={1} />
<CustomCounter targetNumber={recentDeployment?.stuck} timeInSeconds={1} />
</p>
<p className='text-sm text-slate-500'>Created</p>
<p className='text-sm text-slate-500'>Stuck</p>
</div>
<div className='p-2 sm:p-3 large:p-4 flex flex-col border border-slate-500 border-dashed'>
<p className='text-base font-bold text-white-body'>
<CustomCounter targetNumber={1} timeInSeconds={1} />
<CustomCounter targetNumber={recentDeployment?.completed} timeInSeconds={1} />
</p>
<p className='text-sm text-slate-500'>Rejected</p>
<p className='text-sm text-slate-500'>Completed</p>
</div>
</div>
}
@@ -0,0 +1,45 @@
import React from 'react'
import ModalWrapper from '../modals/ModalWrapper'
import MainBtn from '../MainBtn'
export default function RebuildModal({data={}, templateRebuild, closeModal, proceedFunc}) {
return (
<ModalWrapper maxWidth='max-w-sm'>
<div className='relative bg-white rounded-lg shadow-round_black dark:border-[1px] dark:border-[#1E2027] dark:bg-black-box dark:text-white'>
{/* <!-- Modal header --> */}
{/* <div className="p-8 sm:p-12 flex items-center justify-between border-b rounded-t border-gray-300 dark:border-gray-600">
<h3 className="text-xl font-semibold text-gray-900 dark:text-white">
EDIT
</h3>
<button onClick={closeModal} type="button" className="text-gray-400 bg-transparent hover:bg-gray-200 hover:text-gray-900 rounded-lg text-sm w-8 h-8 ms-auto inline-flex justify-center items-center dark:hover:bg-gray-600 dark:hover:text-white" data-modal-hide="default-modal">
<svg className="w-3 h-3" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 14 14">
<path stroke="currentColor" strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="m1 1 6 6m0 0 6 6M7 7l6-6M7 7l-6 6"/>
</svg>
<span className="sr-only">Close modal</span>
</button>
</div> */}
{/* <!-- Modal body --> */}
<div className='p-8 sm:p-12 mb-4 flex flex-col flex-wrap gap-4 lg:gap-8'>
<div className='w-full text-center'>
<p className='text-lg font-semibold mb-1'>Please confirm you want product rebuild to start</p>
{templateRebuild.isPending && <p className='text-sm text-emerald-600'>Rebuild started ...</p>}
</div>
<div className='flex justify-between items-center gap-4'>
<MainBtn
onClick={proceedFunc}
className={`bg-primary dark:bg-primary-dark px-2 py-1 mt-4 rounded-md text-white font-medium sm:self-end`}
text='Proceed'
/>
<MainBtn
type='button'
className={`bg-red-500 px-2 py-1 mt-4 rounded-md text-white font-medium sm:self-end`}
text='Cancel'
onClick={closeModal}
/>
</div>
</div>
</div>
</ModalWrapper>
)
}
@@ -1,12 +1,13 @@
import {useLocation, useNavigate, Link} from 'react-router-dom'
import { useQuery, useMutation } from '@tanstack/react-query'
import { FaCaretDown } from "react-icons/fa";
import {useQuery, useMutation} from '@tanstack/react-query'
import {FaCaretDown} from "react-icons/fa";
import BreadcrumbCom from '../breadcrumb/BreadcrumbCom'
import {useEffect, useState} from 'react';
import RouteLinks from '../../RouteLinks';
import { getSubscriptionsView, updateTemplate, updateCustomTemplate } from '../../services/siteServices'
import {getSubscriptionsView, updateTemplate, updateCustomTemplate, rebuildTemplate} from '../../services/siteServices'
import queryKeys from '../../services/queryKeys'
import getDateTimeFromDateString from '../../helpers/getDateTimeFromDateString';
import RebuildModal from './RebuildModal';
export default function SubscriptionViewCom() {
@@ -14,16 +15,16 @@ export default function SubscriptionViewCom() {
const {state} = useLocation()
const navigate = useNavigate()
const [reqStatus, setReqStatus] = useState({loading: false, type: '', error: false, success: false})
const [rebuildStatus, setRebuildStatus] = useState({status: false, data: {}})
const [values, setValues] = useState({custom_id: '', template_uid: ''})
const handleValueChange = ({target:{name, value}}) => {
if(name == 'custom_template'){
const handleValueChange = ({target: {name, value}}) => {
if (name == 'custom_template') {
setValues(prev => ({...prev, custom_id: value}))
}else if (name == 'template') {
} else if (name == 'template') {
setValues(prev => ({...prev, template_uid: value}))
}else{
} else {
setValues(prev => ({...prev}))
}
}
@@ -34,7 +35,7 @@ export default function SubscriptionViewCom() {
}
}, [])
const {data, isFetching, isError, error} = useQuery({
const {data, isFetching, isError, error} = useQuery({
queryKey: queryKeys.subscriptions_view,
queryFn: () => {
// const filterData = filter?.type ? {[filter?.type]: filter.id} : {}
@@ -63,6 +64,17 @@ export default function SubscriptionViewCom() {
// }
// },[data])
const templateRebuild = useMutation({
mutationFn: (fields) => {
return rebuildTemplate(fields)
},
onSettled: () => {
setTimeout(() => {
setRebuildStatus({status: false, data: {}})
templateRebuild.reset()
}, 3000)
}
})
const templateUpdate = useMutation({
mutationFn: (fields) => {
@@ -73,7 +85,7 @@ export default function SubscriptionViewCom() {
// onSuccess: (res) => {
// },
onSettled: () => {
setTimeout(()=>{
setTimeout(() => {
templateUpdate.reset()
}, 3000)
}
@@ -88,7 +100,7 @@ export default function SubscriptionViewCom() {
// onSuccess: (res) => {
// },
onSettled: () => {
setTimeout(()=>{
setTimeout(() => {
customTemplateUpdate.reset()
}, 3000)
}
@@ -102,6 +114,13 @@ export default function SubscriptionViewCom() {
templateUpdate.mutate(reqData)
}
const handleRebuildTemplate = () => {
const reqData = {
subscription_uid: state?.subscriptionUID,
}
templateRebuild.mutate(reqData)
}
const handleUpdateCustomTemplate = () => {
const reqData = {
subscrtiption_uid: state?.subscriptionUID,
@@ -113,89 +132,142 @@ export default function SubscriptionViewCom() {
return (
<div className='w-full flex flex-col gap-8'>
<BreadcrumbCom title={`Subscription View [${state?.subscriptionUID}]`} paths={['Dashboard', 'Subscription View']}/>
<BreadcrumbCom title={`Subscription View [${state?.subscriptionUID}]`}
paths={['Dashboard', 'Subscription View']}/>
{isFetching ?
<>
<p className='text-slate-800'>Loading...</p>
</>
: isError ?
<p className='text-red-500'>{error.message}</p>
:
{isFetching ?
<>
<div className='w-full box bg-white dark:bg-black-box text-black-body dark:text-white-body overflow-x-auto'>
<table className="py-2 w-full text-sm bg-[aliceblue] dark:bg-transparent rounded-[10px]">
<tbody>
<p className='text-slate-800'>Loading...</p>
</>
: isError ?
<p className='text-red-500'>{error.message}</p>
:
<>
<div
className='w-full box bg-white dark:bg-black-box text-black-body dark:text-white-body overflow-x-auto'>
<table className="py-2 w-full text-sm bg-[aliceblue] dark:bg-transparent rounded-[10px]">
<tbody>
<tr className="py-2 border-t border-dashed border-slate-300">
<td className="px-2 py-2">
<div className="text-left">
<div className="text-base font-semibold">{getDateTimeFromDateString(selectedSubscription?.added)}</div>
<div className="text-base font-semibold">{getDateTimeFromDateString(selectedSubscription?.updated)}</div>
<div className="text-base font-semibold">ID: {selectedSubscription?.id}</div>
</div>
</td>
<td className="px-2">
<div className="text-left">
<div className="text-base font-semibold">{selectedSubscription?.product_id}</div>
<div
className="text-base font-semibold">{selectedSubscription?.product_id}</div>
<div><a href={`http://${selectedSubscription?.primary_server}:${selectedSubscription?.provision_port}`}
target='_blank'
rel="noreferrer">{selectedSubscription?.primary_server}:{selectedSubscription?.provision_port}</a>
</div>
</div>
</td>
<td className="px-2">
<div className="text-left">
<div className="text-base font-semibold">{selectedSubscription?.internal_url}
<br /><span>Template :</span> {selectedSubscription?.product_template}
<br /><span>Custom :</span> {selectedSubscription?.custom_template}
<span className="text-base font-semibold">
<a href={`https://${selectedSubscription?.internal_url}`}
target='_blank'
rel="noreferrer">{selectedSubscription?.internal_url}</a>
</span>
<br/>
<span className="text-base font-semibold">
<a href={`${selectedSubscription?.external_url}`}
target='_blank'
rel="noreferrer">{selectedSubscription?.external_url}</a>
</span>
<br/>
<div className="text-base font-semibold">
<br/><span>Template :</span> {selectedSubscription?.product_template}
<br/><span>Custom :</span> {selectedSubscription?.custom_template}
</div>
</div>
</td>
<td className="px-2">
<div className="text-right">
<div className="text-base font-semibold">{selectedSubscription?.status}</div>
<div
className="text-base font-semibold">{selectedSubscription?.status}</div>
</div>
</td>
<td className="px-2">
<div className="text-right">
<button name='template'
onClick={() => setRebuildStatus({status: true, data: {}})}
className={`rounded-md p-2 bg-primary text-white text-center`}>
Rebuild
</button>
</div>
</td>
</tr>
</tbody>
</table>
</div>
<div className='box bg-white dark:bg-black-box text-black-body dark:text-white-body'>
<div className='w-full'>
<label className='font-medium'>Assign Template</label>
<div className='flex flex-col xs:flex-row md:items-center gap-2'>
<div className='w-full h-10 relative overflow-hidden rounded-md'>
<select name='template' value={currentTemplate || values.template_uid} onChange={handleValueChange} className='w-full h-full p-2 appearance-none dark:bg-transparent border-0 dark:border-1 border-white ring-0 outline-none'>
<option value=''>None</option>
{availableTemplates && availableTemplates.map(item => (
<option key={item?.template_uid} value={item?.template_uid}>{`${item?.product_id}-${item?.provision_name}`}</option>
))}
</select>
<FaCaretDown className='text-base absolute top-1/2 -translate-y-1/2 right-2' />
</div>
<button name='template' onClick={handleUpdateTemplate} disabled={(templateUpdate.isPending || !values.template_uid)} className={`rounded-md p-2 bg-primary text-white text-center ${(templateUpdate.isPending || !values.template_uid) && 'opacity-50'}`}>Update</button>
</div>
<p className={`p-2 mt-4 ${templateUpdate.isSuccess ? 'text-emerald-500' : 'text-red-500'}`}>{templateUpdate.isSuccess ? 'Template updated' : templateUpdate.isSuccess ? 'Unable to complete request, try again' : ''}</p>
</tbody>
</table>
</div>
</div>
<div className='box bg-white dark:bg-black-box text-black-body dark:text-white-body'>
<div className='box bg-white dark:bg-black-box text-black-body dark:text-white-body'>
<div className='w-full'>
<label className='font-medium'>Assign Custom Template</label>
<div className='flex flex-col xs:flex-row md:items-center gap-2'>
<div className='w-full h-10 relative overflow-hidden rounded-md'>
<select name='custom_template' value={currentCustomTem || values.custom_id} onChange={handleValueChange} className='w-full h-full p-2 appearance-none dark:bg-transparent border-0 dark:border-1 border-white ring-0 outline-none'>
<option value=''>None</option>
{customTemplates && customTemplates.map(item => (
<option key={item?.custom_id} value={item?.custom_id}>{`${item?.custom_id}-${item?.provision_name}`}</option>
))}
</select>
<FaCaretDown className='text-base absolute top-1/2 -translate-y-1/2 right-2' />
<div className='w-full'>
<label className='font-medium'>Assign Template</label>
<div className='flex flex-col xs:flex-row md:items-center gap-2'>
<div className='w-full h-10 relative overflow-hidden rounded-md'>
<select name='template' value={currentTemplate || values.template_uid}
onChange={handleValueChange}
className='w-full h-full p-2 appearance-none dark:bg-transparent border-0 dark:border-1 border-white ring-0 outline-none'>
<option value=''>None</option>
{availableTemplates && availableTemplates.map(item => (
<option key={item?.template_uid}
value={item?.template_uid}>{`${item?.product_id}-${item?.provision_name}`}</option>
))}
</select>
<FaCaretDown className='text-base absolute top-1/2 -translate-y-1/2 right-2'/>
</div>
<button name='template' onClick={handleUpdateTemplate}
disabled={(templateUpdate.isPending || !values.template_uid)}
className={`rounded-md p-2 bg-primary text-white text-center ${(templateUpdate.isPending || !values.template_uid) && 'opacity-50'}`}>Update
</button>
</div>
<button name='custom_template' onClick={handleUpdateCustomTemplate} disabled={(customTemplateUpdate.isPending || !values.custom_id)} className={`rounded-md p-2 bg-primary text-white text-center ${(customTemplateUpdate.isPending || !values.custom_id) && 'opacity-50'}`}>Update</button>
<p className={`p-2 mt-4 ${templateUpdate.isSuccess ? 'text-emerald-500' : 'text-red-500'}`}>{templateUpdate.isSuccess ? 'Template updated' : templateUpdate.isSuccess ? 'Unable to complete request, try again' : ''}</p>
</div>
<p className={`p-2 mt-4 ${customTemplateUpdate.isSuccess ? 'text-emerald-500' : 'text-red-500'}`}>{customTemplateUpdate.isSuccess ? 'Custom Template updated' : customTemplateUpdate.isSuccess ? 'Unable to complete request, try again' : ''}</p>
</div>
</div>
</>
<div className='box bg-white dark:bg-black-box text-black-body dark:text-white-body'>
<div className='w-full'>
<label className='font-medium'>Assign Custom Template</label>
<div className='flex flex-col xs:flex-row md:items-center gap-2'>
<div className='w-full h-10 relative overflow-hidden rounded-md'>
<select name='custom_template' value={currentCustomTem || values.custom_id}
onChange={handleValueChange}
className='w-full h-full p-2 appearance-none dark:bg-transparent border-0 dark:border-1 border-white ring-0 outline-none'>
<option value=''>None</option>
{customTemplates && customTemplates.map(item => (
<option key={item?.custom_id}
value={item?.custom_id}>{`${item?.custom_id}-${item?.provision_name}`}</option>
))}
</select>
<FaCaretDown className='text-base absolute top-1/2 -translate-y-1/2 right-2'/>
</div>
<button name='custom_template' onClick={handleUpdateCustomTemplate}
disabled={(customTemplateUpdate.isPending || !values.custom_id)}
className={`rounded-md p-2 bg-primary text-white text-center ${(customTemplateUpdate.isPending || !values.custom_id) && 'opacity-50'}`}>Update
</button>
</div>
<p className={`p-2 mt-4 ${customTemplateUpdate.isSuccess ? 'text-emerald-500' : 'text-red-500'}`}>{customTemplateUpdate.isSuccess ? 'Custom Template updated' : customTemplateUpdate.isSuccess ? 'Unable to complete request, try again' : ''}</p>
</div>
</div>
</>
}
{rebuildStatus?.status &&
<RebuildModal data={{}} templateRebuild={templateRebuild} proceedFunc={handleRebuildTemplate}
closeModal={() => setRebuildStatus({status: false, data: {}})}/>}
</div>
)
}
+8
View File
@@ -124,6 +124,14 @@ export const getProductsTemplate = (reqData) => {
return getAuxEnd(`/products-templates`, postData)
}
// FUNCTION TO INITIATE TEMPLATE REBUILD
export const rebuildTemplate = (reqData) => {
let postData = {
...reqData
}
return postAuxEnd('/rebuild-template', postData, false)
}
// FUNCTION TO UPDATE TEMPLATE
export const updateTemplate = (reqData) => {
let postData = {