Compare commits

..

19 Commits

Author SHA1 Message Date
victorAnumudu 8ee793d11e text truncated 2026-02-09 19:11:17 +01:00
ameye 46f17cbdfe Merge branch 'template-payload-fix' of MERMS/MermsPanelReactJS into master 2026-01-21 09:45:48 +00:00
victorAnumudu 283994e43a pauload fixed 2026-01-21 10:25:56 +01:00
ameye b7d242ff0a Merge branch 'template-media-set' of MERMS/MermsPanelReactJS into master 2026-01-21 08:44:57 +00:00
victorAnumudu f6bae30bdd btn name changed 2026-01-21 04:19:05 +01:00
victorAnumudu a7e2e865de added template media set endpoint 2026-01-21 03:27:48 +01:00
ameye 51887cf0d6 Merge branch 'upload-btn-bug' of MERMS/MermsPanelReactJS into master 2026-01-20 17:11:43 +00:00
victorAnumudu 5ea1047356 image pop up added 2026-01-20 17:15:58 +01:00
victorAnumudu 9b9a7cc5da fixed upload btn display 2026-01-20 14:31:55 +01:00
ameye 290e1fbd7e Merge branch 'image-list-resized' of MERMS/MermsPanelReactJS into master 2026-01-19 20:44:45 +00:00
victorAnumudu 6884aa19b2 fixed image size 2026-01-19 19:36:21 +01:00
CHIEFSOFT\ameye 597a45dcba site image 2026-01-18 18:13:58 -05:00
CHIEFSOFT\ameye 4f7274c30c load template settings 2026-01-17 19:05:12 -05:00
ameye 290356780c Merge branch 'config-temp' of MERMS/MermsPanelReactJS into master 2026-01-13 08:14:09 +00:00
victorAnumudu bd1450887b added config template page 2026-01-13 05:01:23 +01:00
CHIEFSOFT\ameye 923a2483ed Added report starter 2026-01-12 12:08:13 -05:00
ameye 7f0ccf35b2 Merge branch 'report-endpoints' of MERMS/MermsPanelReactJS into master 2026-01-09 19:09:59 +00:00
victorAnumudu af2fdcede6 added endpoint for payment, product and system reports 2026-01-09 18:10:34 +01:00
ameye a9f2136125 Merge branch 'system-table' of MERMS/MermsPanelReactJS into master 2026-01-09 12:24:14 +00:00
13 changed files with 845 additions and 361 deletions
+7
View File
@@ -51,4 +51,11 @@ button{
.accordion-button, .accordion-button:not(.collapsed) { .accordion-button, .accordion-button:not(.collapsed) {
background-color: transparent!important; background-color: transparent!important;
}
@media (min-width: 992px) {
.modal-50 {
min-width: 50%;
max-width: 50%;
}
} }
+20 -15
View File
@@ -41,22 +41,27 @@ export default function Products() {
</div> </div>
: :
<div className="row m-b-20"> <div className="row m-b-20">
{products && products.map((product, index) => ( {products && products.map((product, index) =>
<div key={product.uid+index} className={`col-xxs-6 col-xl-4 col-xxl-6 mb-2 mb-xxl-0`}> {
<Link to={productPath(product?.product_id)} > // let productName = product?.name?.length > 14 ? product?.name?.substring(0, 14) + '...' : product?.name
<div className={`d-flex align-items-center extraProductCard ${product?.icon_style}`} style={{borderColor:'black', borderWidth: '2px'}} > return (
<div className="icon-container img-icon m-r-20 bg-light-gray rounded"> <div key={product.uid+index} className={`col-12 col-lg-6 mb-2 mb-xxl-0`}>
<i className={`fa ${product?.product_icon} text-primary`}></i> <Link to={productPath(product?.product_id)} >
<div className={`d-flex align-items-center extraProductCard ${product?.icon_style}`} style={{borderColor:'black', borderWidth: '2px'}} >
<div className="icon-container img-icon m-r-20 bg-light-gray rounded">
<i className={`fa ${product?.product_icon} text-primary`}></i>
</div>
<div className="report-details overflow-hidden">
<p><span style={{fontWeight: 'bolder', color: '#00557A'}}>{product?.status_text}</span></p>
<h4><span className='w-100 d-inline-block text-truncate' style={{paddingLeft: '10px'}}>{product?.name}</span></h4>
</div>
</div> </div>
<div className="report-details"> </Link>
<p><span style={{fontWeight: 'bolder', color: '#00557A'}}>{product?.status_text}</span></p>
<h4><span className='text-truncate' style={{paddingLeft: '10px'}}>{product?.name}</span></h4> </div>
</div> )
</div> }
</Link> )}
</div>
))}
</div> </div>
} }
<div className="apexchart-wrapper"> <div className="apexchart-wrapper">
+1 -1
View File
@@ -117,7 +117,7 @@ console.log('imageLink', imageLink)
<div className="row"> <div className="row">
<div className="col-xl-6 col-xxl-4 m-b-30"> <div className="col-xl-6 col-xxl-4 m-b-30">
<div className="card card-statistics h-50 mb-0 widget-support-list"> <div className="card card-statistics mb-0 widget-support-list">
<div className="card-header"> <div className="card-header">
<div className="card-heading"> <div className="card-heading">
<h4 className="card-title">Upload File</h4> <h4 className="card-title">Upload File</h4>
+1 -1
View File
@@ -66,7 +66,7 @@ export default function ProductActive({productData}){
</button> </button>
</div> </div>
</div> </div>
<div className="card-body" style={{minHeight: '680px'}}> <div className="card-body" style={{minHeight: '600px', maxHeight: '600px'}}>
<iframe ref={iframe} style={{borderWidth: '0px'}} src={externalUrl} width="100%" height="600" title={externalUrl}></iframe> <iframe ref={iframe} style={{borderWidth: '0px'}} src={externalUrl} width="100%" height="600" title={externalUrl}></iframe>
</div> </div>
<div className="p-4 ml-auto"> <div className="p-4 ml-auto">
+26 -6
View File
@@ -5,6 +5,7 @@ import queryKeys from '../../../services/queryKeys';
import { useSelector } from 'react-redux'; import { useSelector } from 'react-redux';
import { useQuery } from '@tanstack/react-query'; import { useQuery } from '@tanstack/react-query';
import sortObjectByListOrder from '../../../helpers/sortObjectByListOrder' import sortObjectByListOrder from '../../../helpers/sortObjectByListOrder'
import TemplateConfigure from './TemplateConfigure';
const Settings = memo(({productData}) => { const Settings = memo(({productData}) => {
@@ -24,7 +25,7 @@ const Settings = memo(({productData}) => {
}) })
const settingsConfig = configData?.data?.settings_items const settingsConfig = configData?.data?.settings_items
// console.log('CONFIG DATA...', settingsConfig) // console.log('CONFIG DATA...', settingsConfig)
// console.log('configData', configData?.data?.subscription_template)
const [fieldsChanged, setFieldsChanged] = useState(false) const [fieldsChanged, setFieldsChanged] = useState(false)
@@ -81,12 +82,12 @@ const Settings = memo(({productData}) => {
</div> </div>
</div> </div>
: :
<div className="tab tab-vertical"> <div className="d-flex">
<ul className="nav nav-tabs" role="tablist"> <ul className="bg-body-secondary flex-column nav" role="tablist" style={{width: '25%', minHeight: '670px', maxHeight: '670px'}}>
<> <>
{Object.entries(sortedSettingsConfig).map(([key, value], index) => ( {Object.entries(sortedSettingsConfig).map(([key, value], index) => (
<li key={key} className="nav-item"> <li key={key} className="nav-item">
<a className={`nav-link ${(activeTab == value.controls || (index == 0 & !activeTab)) && 'active show'}`} <p className={`text-black nav-link ${(activeTab == value.controls || (index == 0 & !activeTab)) && 'active show bg-primary text-white'}`}
id={key} id={key}
// data-bs-toggle="pill" // data-bs-toggle="pill"
// data-bs-target={`#${value.controls}`} // data-bs-target={`#${value.controls}`}
@@ -97,12 +98,27 @@ const Settings = memo(({productData}) => {
onClick={()=>handleChangeTab(value.controls)} onClick={()=>handleChangeTab(value.controls)}
> >
{value.title} {value.title}
</a> </p>
</li> </li>
))} ))}
{configData?.data?.subscription_template &&
<li className="mt-auto nav-item">
<p className={`text-black nav-link ${(activeTab == 'config_temp') && 'active show bg-primary text-white'}`}
// data-bs-toggle="pill"
// data-bs-target={`#${value.controls}`}
type="button"
// role="tab"
// aria-controls={value.controls}
// aria-selected="true"
onClick={()=>handleChangeTab('config_temp')}
>
Configure Template
</p>
</li>
}
</> </>
</ul> </ul>
<div className="tab-content"> <div className="p-3 tab-content" style={{width: '75%'}}>
<> <>
{Object.entries(sortedSettingsConfig).map(([key, value], index) => ( {Object.entries(sortedSettingsConfig).map(([key, value], index) => (
<div key={key} className={`tab-pane fade ${(activeTab == value.controls || (index == 0 & !activeTab)) && 'active show'}`} <div key={key} className={`tab-pane fade ${(activeTab == value.controls || (index == 0 & !activeTab)) && 'active show'}`}
@@ -112,6 +128,10 @@ const Settings = memo(({productData}) => {
<GeneralTab tabKey={key} name={value.title} data={value.data} isCustom={value.custom} productData={productData} backendValues={settingsData} setFieldsChanged={setFieldsChanged} /> <GeneralTab tabKey={key} name={value.title} data={value.data} isCustom={value.custom} productData={productData} backendValues={settingsData} setFieldsChanged={setFieldsChanged} />
</div> </div>
))} ))}
<div className={`tab-pane fade ${(activeTab == 'config_temp') && 'active show'}`}
>
<TemplateConfigure productData={productData} />
</div>
</> </>
</div> </div>
</div> </div>
@@ -0,0 +1,130 @@
import React, {memo, useState} from 'react'
import getImage from "../../../utils/getImage";
import {useMutation, useQuery, useQueryClient} from '@tanstack/react-query';
import queryKeys from '../../../services/queryKeys';
import {getTemplateConfig} from '../../../services/services';
import {Link} from "react-router-dom";
import siteLinks from "../../../links/siteLinks";
import UploadModal from './UploadModal';
const TemplateConfigure = ({productData}) => {
const [selectedSectionDetails, setSelectedSectionDetails] = useState({})
// /panel/myproduct/template-config
const queryClient = useQueryClient()
const {data: templateData, isFetching, isError, error} = useQuery({
queryKey: queryKeys.myTemplateConfig,
queryFn: () => {
let reqData = {
token: localStorage.getItem('token'), // USER TOKEN
uid: localStorage.getItem('uid'), // USER UID
product_id: productData?.product_id
}
return getTemplateConfig(reqData)
},
staleTime: 0
})
const templateResponse = templateData?.data
const templateImages = templateResponse?.template_images?.data;
// debugger;
console.log("templateResponse", templateResponse);
// const currentColorUID = templateResponse?.current_colorstyle_uid
// const color_styles = templateResponse?.color_styles
// const custom_template_name = templateResponse?.custom_template_name
return <>
<div className="card card-statistics">
{isFetching ?
<>
<div className="row">
<div className="col-12">
<p className='text-mute'>Loading...</p>
</div>
</div>
</>
: isError ?
<div className="row">
<div className="col-12">
<p className='text-danger'>{error?.message}</p>
</div>
</div>
:
<>
<div className="card-header">
<div className="card-heading">
<h4 className="card-title"
style={{textTransform: 'none'}}>{templateResponse?.template_name}</h4>
</div>
</div>
<div>
<div className="col-12">
<div>
<div>
<div>
<h4>Image List</h4>
</div>
</div>
<div>
<ul className="list-unstyled">
{templateImages && templateImages.map(
(item) => {
const currImage = item?.default_val;
return (
<li className="media">
<div style={{
display: 'flex',
flexDirection: 'row',
padding: '5px',
backgroundColor: 'aliceblue',
margin: '2px',
maxHeight: '150px'
}}>
<div className='d-flex justify-content-center align-items-center' style={{padding: '6px', width: '120px', height: '100px'}}>
<img className="mb-xxs-0 img-fluid"
style={{height: 'auto', maxHeight: '100px'}}
src={currImage} alt="image"/>
</div>
<div className="media-body" style={{padding: '2px'}}>
<div style={{
display: 'flex',
flexDirection: 'column'
}}>
<div style={{textAlign: 'right',width: '100%'}}></div>
{/* [Change Image] */}
<label onClick={()=>setSelectedSectionDetails(item)} className='w-100 text-end' data-bs-toggle="modal" data-bs-target="#verticalCenter" style={{cursor: 'pointer'}}>[Change Image]</label>
{/* <input id={item?.id} name={item?.id} className="d-none form-control form-control-sm" type="file" onChange={handleFileChange}/> */}
<div>
<h5 className="mt-0 mb-1">{item?.name}</h5>
{item?.description}
</div>
</div>
</div>
</div>
</li>
)
}
)
}
</ul>
</div>
</div>
</div>
</div>
</>
} </div>
<UploadModal productId={productData?.product_id} selectedSectionDetails={selectedSectionDetails} />
</>
}
export default TemplateConfigure
@@ -0,0 +1,168 @@
import React, { useRef, useState } from 'react'
import { Modal } from "bootstrap";
import {useMutation, useQuery, useQueryClient} from '@tanstack/react-query';
import queryKeys from '../../../services/queryKeys';
import {getMediaFileList, templateMediaSet} from '../../../services/services';
export default function UploadModal({productId, selectedSectionDetails}) {
const queryClient = useQueryClient()
const [selectedFile, setSelectedFile] = useState('')
const handleSelectedFile = (file_uid) => {
// if(selectedFile.length && selectedFile.includes(file_uid)){
// let indexOfItem = selectedFile.indexOf(file_uid)
// let oldFiles = [...selectedFile]
// oldFiles.splice(indexOfItem, 1)
// setSelectedFile(oldFiles)
// }else{
// setSelectedFile(prev => [...prev, file_uid])
// }
setSelectedFile(file_uid)
}
const modalRef = useRef(null)
const dismissModal = () => {
const body = document.querySelector('body')
body.removeAttribute('style')
// body.classList.toggle('modal-open')
const modalBackdrop = document.querySelectorAll('.modal-backdrop')
modalBackdrop.forEach(item => {
if (item) {
item.remove();
}
})
const modal = Modal.getInstance(modalRef.current);
modal && modal.hide();
};
const changeTemplateMediaSet = useMutation({
mutationFn: (fields) => {
if(!fields.file_uid){
throw({message: 'Please select a file first!'})
}
return templateMediaSet(fields)
},
onSuccess: (res) => {
// console.log('res', res.data)
if(res.data.resultCode != '0'){
throw({message: res?.data?.resultDescription})
}
setSelectedFile('')
dismissModal() // to close modal
queryClient.refetchQueries({
queryKey: [...queryKeys.myTemplateConfig],
// type: 'active',
// exact: true,
})
},
onSettled: () => {
setTimeout(()=>{
changeTemplateMediaSet.reset()
}, 3000)
}
})
const handleUpload = () => {
let reqData = {
token: localStorage.getItem("token"), // USER TOKEN
uid: localStorage.getItem("uid"), // USER UID
product_id: productId,
file_uid: selectedFile,
image_id: selectedSectionDetails?.id
};
// console.log('reqData', reqData)
changeTemplateMediaSet.mutate(reqData)
}
const {data, isFetching, isError, error} = useQuery({
queryKey: queryKeys.my_files,
queryFn: () => {
let reqData = {
token: localStorage.getItem('token'), // USER TOKEN
uid: localStorage.getItem('uid') // USER UID
}
return getMediaFileList(reqData)
}
})
const mediaFileList = data?.data
// console.log('mediaFileList', mediaFileList) //file_list
return (
<>
{/* Vertical Center Modal */}
<div ref={modalRef} className="modal fade" id="verticalCenter" tabIndex="-1" role="dialog" aria-hidden="false">
<div className="modal-50 modal-dialog modal-dialog-centered modal-50" role="document">
<div className="modal-content">
<div className="modal-header">
<h5 className="modal-title" style={{fontSize: '18px'}} id="verticalCenterTitle">Select New Picture</h5>
<button type="button" className="close" data-bs-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div className="modal-body">
{isFetching ?
<>
<div className="col-12">
<p className='text-mute'>Loading...</p>
</div>
</>
: isError ?
<div className="col-12">
<p className='text-danger'>{error?.message}</p>
</div>
:
<div className='row g-5 justify-content-center'>
{mediaFileList?.file_list?.length ?
<>
{mediaFileList?.file_list?.map(item => {
const file_url = (mediaFileList?.media_server + "/" + item?.file_group + "/" + item?.file_uid + "/" + item.filename).toLowerCase();
return(
<div onClick={()=>handleSelectedFile(item?.file_uid)} className={`p-3 text-center col-4`} style={{cursor: 'pointer'}}>
<div className={`p-3 ${(selectedFile == item?.file_uid) && 'bg-light'}`} style={{Height: '250px'}}>
<img key={item?.file_uid} className="img-fluid" style={{}} src={file_url} alt='file-image' />
</div>
</div>
)
})
}
</>
:
<p>No File(s) found!</p>
}
</div>
}
{changeTemplateMediaSet.error &&
<>
<div className="col-12">
<p className='text-danger'>{changeTemplateMediaSet.error.message}</p>
</div>
</>
}
{changeTemplateMediaSet.isSuccess &&
<>
<div className="col-12">
<p className='text-success'>{'subscription is successful'}</p>
</div>
</>
}
</div>
<div className="modal-footer">
<button type="button" className="btn btn-danger" data-bs-dismiss="modal">Cancel</button>
{selectedFile &&
<button type="button" className="btn btn-primary" disabled={changeTemplateMediaSet?.isPending || changeTemplateMediaSet?.isSuccess} onClick={handleUpload}>{changeTemplateMediaSet?.isPending ? 'Applying...' : changeTemplateMediaSet?.isSuccess ? 'Applied' : 'Apply'}</button>
}
</div>
</div>
</div>
</div>
{/* END of Vertical Center Modal */}
</>
)
}
+36 -4
View File
@@ -1,7 +1,27 @@
import React from "react"; import React, { useState } from "react";
import { useQuery } from "@tanstack/react-query";
import { getPaymentReports } from "../../services/services";
import queryKeys from "../../services/queryKeys";
export default function PaymentReportTable() { export default function PaymentReportTable() {
return (<>
const [page, setPage] = useState(0)
const {data, isFetching, isError, error} = useQuery({
queryKey: [...queryKeys.payment_report, page],
queryFn: () => {
let reqData = {
token: localStorage.getItem('token'), // USER TOKEN
uid: localStorage.getItem('uid'), // USER UID
page
}
return getPaymentReports(reqData)
}
})
console.log('DATA', data?.data)
return (
<>
<div className="row"> <div className="row">
<div className="col-md-12 m-b-30"> <div className="col-md-12 m-b-30">
<div className="d-block d-sm-flex flex-nowrap align-items-center"> <div className="d-block d-sm-flex flex-nowrap align-items-center">
@@ -12,6 +32,17 @@ export default function PaymentReportTable() {
</div> </div>
</div> </div>
<div className="row"> <div className="row">
{isFetching ?
<>
<div className="col-12">
<p className='text-mute'>Loading...</p>
</div>
</>
: isError ?
<div className="col-12">
<p className='text-danger'>{error?.message}</p>
</div>
:
<div className="col-lg-12"> <div className="col-lg-12">
<div className="card card-statistics"> <div className="card card-statistics">
<div className="card-body"> <div className="card-body">
@@ -164,7 +195,8 @@ export default function PaymentReportTable() {
</div> </div>
</div> </div>
</div> </div>
}
</div> </div>
</>
</>) )
} }
+184 -151
View File
@@ -1,7 +1,28 @@
import React from "react"; import React, { useState } from "react";
import { useQuery } from "@tanstack/react-query";
import { getProductReports } from "../../services/services";
import queryKeys from "../../services/queryKeys";
export default function ProductReportTable() { export default function ProductReportTable() {
return (<>
const [page, setPage] = useState(0)
const {data, isFetching, isError, error} = useQuery({
queryKey: [...queryKeys.product_report, page],
queryFn: () => {
let reqData = {
token: localStorage.getItem('token'), // USER TOKEN
uid: localStorage.getItem('uid'), // USER UID
page
}
return getProductReports(reqData)
}
})
console.log('DATA', data?.data)
return (
<>
<div className="row"> <div className="row">
<div className="col-md-12 m-b-30"> <div className="col-md-12 m-b-30">
@@ -14,159 +35,171 @@ export default function ProductReportTable() {
</div> </div>
<div className="row"> <div className="row">
<div className="col-lg-12"> {isFetching ?
<div className="card card-statistics"> <>
<div className="card-body"> <div className="col-12">
<div className="export-table-wrapper table-responsive"> <p className='text-mute'>Loading...</p>
<table id="export-table" className="table table-bordered"> </div>
<thead className="thead-light"> </>
<tr> : isError ?
<th>Name</th> <div className="col-12">
<th>Position</th> <p className='text-danger'>{error?.message}</p>
<th>Office</th> </div>
<th>Age</th> :
<th>Start date</th> <div className="col-lg-12">
<th>Salary</th> <div className="card card-statistics">
</tr> <div className="card-body">
</thead> <div className="export-table-wrapper table-responsive">
<tbody> <table id="export-table" className="table table-bordered">
<tr> <thead className="thead-light">
<td>Tiger Nixon</td> <tr>
<td>System Architect</td> <th>Name</th>
<td>Edinburgh</td> <th>Position</th>
<td>61</td> <th>Office</th>
<td>2011/04/25</td> <th>Age</th>
<td>$320,800</td> <th>Start date</th>
</tr> <th>Salary</th>
<tr> </tr>
<td>Garrett Winters</td> </thead>
<td>Accountant</td> <tbody>
<td>Tokyo</td> <tr>
<td>63</td> <td>Tiger Nixon</td>
<td>2011/07/25</td> <td>System Architect</td>
<td>$170,750</td> <td>Edinburgh</td>
</tr> <td>61</td>
<tr> <td>2011/04/25</td>
<td>Ashton Cox</td> <td>$320,800</td>
<td>Junior Technical Author</td> </tr>
<td>San Francisco</td> <tr>
<td>66</td> <td>Garrett Winters</td>
<td>2009/01/12</td> <td>Accountant</td>
<td>$86,000</td> <td>Tokyo</td>
</tr> <td>63</td>
<tr> <td>2011/07/25</td>
<td>Cedric Kelly</td> <td>$170,750</td>
<td>Senior Javascript Developer</td> </tr>
<td>Edinburgh</td> <tr>
<td>22</td> <td>Ashton Cox</td>
<td>2012/03/29</td> <td>Junior Technical Author</td>
<td>$433,060</td> <td>San Francisco</td>
</tr> <td>66</td>
<tr> <td>2009/01/12</td>
<td>Airi Satou</td> <td>$86,000</td>
<td>Accountant</td> </tr>
<td>Tokyo</td> <tr>
<td>33</td> <td>Cedric Kelly</td>
<td>2008/11/28</td> <td>Senior Javascript Developer</td>
<td>$162,700</td> <td>Edinburgh</td>
</tr> <td>22</td>
<tr> <td>2012/03/29</td>
<td>Brielle Williamson</td> <td>$433,060</td>
<td>Integration Specialist</td> </tr>
<td>New York</td> <tr>
<td>61</td> <td>Airi Satou</td>
<td>2012/12/02</td> <td>Accountant</td>
<td>$372,000</td> <td>Tokyo</td>
</tr> <td>33</td>
<tr> <td>2008/11/28</td>
<td>Herrod Chandler</td> <td>$162,700</td>
<td>Sales Assistant</td> </tr>
<td>San Francisco</td> <tr>
<td>59</td> <td>Brielle Williamson</td>
<td>2012/08/06</td> <td>Integration Specialist</td>
<td>$137,500</td> <td>New York</td>
</tr> <td>61</td>
<tr> <td>2012/12/02</td>
<td>Rhona Davidson</td> <td>$372,000</td>
<td>Integration Specialist</td> </tr>
<td>Tokyo</td> <tr>
<td>55</td> <td>Herrod Chandler</td>
<td>2010/10/14</td> <td>Sales Assistant</td>
<td>$327,900</td> <td>San Francisco</td>
</tr> <td>59</td>
<tr> <td>2012/08/06</td>
<td>Colleen Hurst</td> <td>$137,500</td>
<td>Javascript Developer</td> </tr>
<td>San Francisco</td> <tr>
<td>39</td> <td>Rhona Davidson</td>
<td>2009/09/15</td> <td>Integration Specialist</td>
<td>$205,500</td> <td>Tokyo</td>
</tr> <td>55</td>
<tr> <td>2010/10/14</td>
<td>Sonya Frost</td> <td>$327,900</td>
<td>Software Engineer</td> </tr>
<td>Edinburgh</td> <tr>
<td>23</td> <td>Colleen Hurst</td>
<td>2008/12/13</td> <td>Javascript Developer</td>
<td>$103,600</td> <td>San Francisco</td>
</tr> <td>39</td>
<tr> <td>2009/09/15</td>
<td>Jena Gaines</td> <td>$205,500</td>
<td>Office Manager</td> </tr>
<td>London</td> <tr>
<td>30</td> <td>Sonya Frost</td>
<td>2008/12/19</td> <td>Software Engineer</td>
<td>$90,560</td> <td>Edinburgh</td>
</tr> <td>23</td>
<tr> <td>2008/12/13</td>
<td>Quinn Flynn</td> <td>$103,600</td>
<td>Support Lead</td> </tr>
<td>Edinburgh</td> <tr>
<td>22</td> <td>Jena Gaines</td>
<td>2013/03/03</td> <td>Office Manager</td>
<td>$342,000</td> <td>London</td>
</tr> <td>30</td>
<tr> <td>2008/12/19</td>
<td>Charde Marshall</td> <td>$90,560</td>
<td>Regional Director</td> </tr>
<td>San Francisco</td> <tr>
<td>36</td> <td>Quinn Flynn</td>
<td>2008/10/16</td> <td>Support Lead</td>
<td>$470,600</td> <td>Edinburgh</td>
</tr> <td>22</td>
<tr> <td>2013/03/03</td>
<td>Haley Kennedy</td> <td>$342,000</td>
<td>Senior Marketing Designer</td> </tr>
<td>London</td> <tr>
<td>43</td> <td>Charde Marshall</td>
<td>2012/12/18</td> <td>Regional Director</td>
<td>$313,500</td> <td>San Francisco</td>
</tr> <td>36</td>
<tr> <td>2008/10/16</td>
<td>Tatyana Fitzpatrick</td> <td>$470,600</td>
<td>Regional Director</td> </tr>
<td>London</td> <tr>
<td>19</td> <td>Haley Kennedy</td>
<td>2010/03/17</td> <td>Senior Marketing Designer</td>
<td>$385,750</td> <td>London</td>
</tr> <td>43</td>
<tr> <td>2012/12/18</td>
<td>Michael Silva</td> <td>$313,500</td>
<td>Marketing Designer</td> </tr>
<td>London</td> <tr>
<td>66</td> <td>Tatyana Fitzpatrick</td>
<td>2012/11/27</td> <td>Regional Director</td>
<td>$198,500</td> <td>London</td>
</tr> <td>19</td>
<td>2010/03/17</td>
<td>$385,750</td>
</tr>
<tr>
<td>Michael Silva</td>
<td>Marketing Designer</td>
<td>London</td>
<td>66</td>
<td>2012/11/27</td>
<td>$198,500</td>
</tr>
</tbody> </tbody>
</table> </table>
</div>
</div> </div>
</div> </div>
</div> </div>
</div> }
</div> </div>
</>
</>) )
} }
+44 -32
View File
@@ -36,46 +36,58 @@ export default function Reports() {
<> <>
<BreadcrumbComBS title='Reports' paths={['Dashboard', 'Reports']}/> <BreadcrumbComBS title='Reports' paths={['Dashboard', 'Reports']}/>
<div className="row"> <div className="row">
{isFetching ?
<>
<div className="col-12">
<p className='text-mute'>Loading...</p>
</div>
</>
: isError ?
<div className="col-12">
<p className='text-danger'>{error?.message}</p>
</div>
:
<div>
<div> <div>
<div> <div className="card card-statistics" style={{minHeight: '550px'}}>
<div className="card card-statistics" style={{minHeight: '550px'}}> {/*<div className="card-header">*/}
{/*<div className="card-header">*/} {/* <div className="card-heading">*/}
{/* <div className="card-heading">*/} {/* <h4 className="card-title"> Tab vertical </h4>*/}
{/* <h4 className="card-title"> Tab vertical </h4>*/} {/* </div>*/}
{/* </div>*/} {/*</div>*/}
{/*</div>*/} <div className="card-body">
<div className="card-body"> <div className="tab tab-vertical">
<div className="tab tab-vertical">
{/* <!-- Tabs --> */}
{/* <!-- Tabs --> */} <ul className="nav nav-tabs" id="myTab" role="tablist">
<ul className="nav nav-tabs" id="myTab" role="tablist"> {sortedReportTopicList && sortedReportTopicList.map((item, index) => {
{sortedReportTopicList && sortedReportTopicList.map((item, index) => { return (
return ( <li key={index} className="nav-item" role="presentation">
<li key={index} className="nav-item" role="presentation"> <a className={`nav-link ${index == 0 && 'active'}`} id={`tab-${item?.url}`} href="#" data-bs-toggle="tab" data-bs-target={`#content-${item?.url}`} type="button" role="tab">
<a className={`nav-link ${index == 0 && 'active'}`} id={`tab-${item?.url}`} href="#" data-bs-toggle="tab" data-bs-target={`#content-${item?.url}`} type="button" role="tab"> {item?.name}
{item?.name} </a>
</a> </li>
</li> )
) })}
})} </ul>
</ul>
{/* <!-- Tab Content --> */} {/* <!-- Tab Content --> */}
<div className="tab-content"> <div className="tab-content">
{sortedReportTopicList && sortedReportTopicList.map((item, index) => { {sortedReportTopicList && sortedReportTopicList.map((item, index) => {
return ( return (
<div key={index} className={`tab-pane fade show ${index == 0 && 'active'}`} id={`content-${item?.url}`} role="tabpanel"> <div key={index} className={`tab-pane fade show ${index == 0 && 'active'}`} id={`content-${item?.url}`} role="tabpanel">
{renderedTable[item?.url]} {renderedTable[item?.url]}
</div> </div>
) )
})} })}
</div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
}
</div>
</> </>
) )
} }
+184 -151
View File
@@ -1,7 +1,28 @@
import React from "react"; import React, { useState } from "react";
import { useQuery } from "@tanstack/react-query";
import { getSystemReports } from "../../services/services";
import queryKeys from "../../services/queryKeys";
export default function SystemReportTable() { export default function SystemReportTable() {
return (<>
const [page, setPage] = useState(0)
const {data, isFetching, isError, error} = useQuery({
queryKey: [...queryKeys.system_report, page],
queryFn: () => {
let reqData = {
token: localStorage.getItem('token'), // USER TOKEN
uid: localStorage.getItem('uid'), // USER UID
page
}
return getSystemReports(reqData)
},
})
console.log('DATA', data?.data)
return (
<>
<div className="row"> <div className="row">
<div className="col-md-12 m-b-30"> <div className="col-md-12 m-b-30">
@@ -14,159 +35,171 @@ export default function SystemReportTable() {
</div> </div>
<div className="row"> <div className="row">
<div className="col-lg-12"> {isFetching ?
<div className="card card-statistics"> <>
<div className="card-body"> <div className="col-12">
<div className="export-table-wrapper table-responsive"> <p className='text-mute'>Loading...</p>
<table id="export-table" className="table table-bordered"> </div>
<thead className="thead-light"> </>
<tr> : isError ?
<th>Name</th> <div className="col-12">
<th>Position</th> <p className='text-danger'>{error?.message}</p>
<th>Office</th> </div>
<th>Age</th> :
<th>Start date</th> <div className="col-lg-12">
<th>Salary</th> <div className="card card-statistics">
</tr> <div className="card-body">
</thead> <div className="export-table-wrapper table-responsive">
<tbody> <table id="export-table" className="table table-bordered">
<tr> <thead className="thead-light">
<td>Tiger Nixon</td> <tr>
<td>System Architect</td> <th>Name</th>
<td>Edinburgh</td> <th>Position</th>
<td>61</td> <th>Office</th>
<td>2011/04/25</td> <th>Age</th>
<td>$320,800</td> <th>Start date</th>
</tr> <th>Salary</th>
<tr> </tr>
<td>Garrett Winters</td> </thead>
<td>Accountant</td> <tbody>
<td>Tokyo</td> <tr>
<td>63</td> <td>Tiger Nixon</td>
<td>2011/07/25</td> <td>System Architect</td>
<td>$170,750</td> <td>Edinburgh</td>
</tr> <td>61</td>
<tr> <td>2011/04/25</td>
<td>Ashton Cox</td> <td>$320,800</td>
<td>Junior Technical Author</td> </tr>
<td>San Francisco</td> <tr>
<td>66</td> <td>Garrett Winters</td>
<td>2009/01/12</td> <td>Accountant</td>
<td>$86,000</td> <td>Tokyo</td>
</tr> <td>63</td>
<tr> <td>2011/07/25</td>
<td>Cedric Kelly</td> <td>$170,750</td>
<td>Senior Javascript Developer</td> </tr>
<td>Edinburgh</td> <tr>
<td>22</td> <td>Ashton Cox</td>
<td>2012/03/29</td> <td>Junior Technical Author</td>
<td>$433,060</td> <td>San Francisco</td>
</tr> <td>66</td>
<tr> <td>2009/01/12</td>
<td>Airi Satou</td> <td>$86,000</td>
<td>Accountant</td> </tr>
<td>Tokyo</td> <tr>
<td>33</td> <td>Cedric Kelly</td>
<td>2008/11/28</td> <td>Senior Javascript Developer</td>
<td>$162,700</td> <td>Edinburgh</td>
</tr> <td>22</td>
<tr> <td>2012/03/29</td>
<td>Brielle Williamson</td> <td>$433,060</td>
<td>Integration Specialist</td> </tr>
<td>New York</td> <tr>
<td>61</td> <td>Airi Satou</td>
<td>2012/12/02</td> <td>Accountant</td>
<td>$372,000</td> <td>Tokyo</td>
</tr> <td>33</td>
<tr> <td>2008/11/28</td>
<td>Herrod Chandler</td> <td>$162,700</td>
<td>Sales Assistant</td> </tr>
<td>San Francisco</td> <tr>
<td>59</td> <td>Brielle Williamson</td>
<td>2012/08/06</td> <td>Integration Specialist</td>
<td>$137,500</td> <td>New York</td>
</tr> <td>61</td>
<tr> <td>2012/12/02</td>
<td>Rhona Davidson</td> <td>$372,000</td>
<td>Integration Specialist</td> </tr>
<td>Tokyo</td> <tr>
<td>55</td> <td>Herrod Chandler</td>
<td>2010/10/14</td> <td>Sales Assistant</td>
<td>$327,900</td> <td>San Francisco</td>
</tr> <td>59</td>
<tr> <td>2012/08/06</td>
<td>Colleen Hurst</td> <td>$137,500</td>
<td>Javascript Developer</td> </tr>
<td>San Francisco</td> <tr>
<td>39</td> <td>Rhona Davidson</td>
<td>2009/09/15</td> <td>Integration Specialist</td>
<td>$205,500</td> <td>Tokyo</td>
</tr> <td>55</td>
<tr> <td>2010/10/14</td>
<td>Sonya Frost</td> <td>$327,900</td>
<td>Software Engineer</td> </tr>
<td>Edinburgh</td> <tr>
<td>23</td> <td>Colleen Hurst</td>
<td>2008/12/13</td> <td>Javascript Developer</td>
<td>$103,600</td> <td>San Francisco</td>
</tr> <td>39</td>
<tr> <td>2009/09/15</td>
<td>Jena Gaines</td> <td>$205,500</td>
<td>Office Manager</td> </tr>
<td>London</td> <tr>
<td>30</td> <td>Sonya Frost</td>
<td>2008/12/19</td> <td>Software Engineer</td>
<td>$90,560</td> <td>Edinburgh</td>
</tr> <td>23</td>
<tr> <td>2008/12/13</td>
<td>Quinn Flynn</td> <td>$103,600</td>
<td>Support Lead</td> </tr>
<td>Edinburgh</td> <tr>
<td>22</td> <td>Jena Gaines</td>
<td>2013/03/03</td> <td>Office Manager</td>
<td>$342,000</td> <td>London</td>
</tr> <td>30</td>
<tr> <td>2008/12/19</td>
<td>Charde Marshall</td> <td>$90,560</td>
<td>Regional Director</td> </tr>
<td>San Francisco</td> <tr>
<td>36</td> <td>Quinn Flynn</td>
<td>2008/10/16</td> <td>Support Lead</td>
<td>$470,600</td> <td>Edinburgh</td>
</tr> <td>22</td>
<tr> <td>2013/03/03</td>
<td>Haley Kennedy</td> <td>$342,000</td>
<td>Senior Marketing Designer</td> </tr>
<td>London</td> <tr>
<td>43</td> <td>Charde Marshall</td>
<td>2012/12/18</td> <td>Regional Director</td>
<td>$313,500</td> <td>San Francisco</td>
</tr> <td>36</td>
<tr> <td>2008/10/16</td>
<td>Tatyana Fitzpatrick</td> <td>$470,600</td>
<td>Regional Director</td> </tr>
<td>London</td> <tr>
<td>19</td> <td>Haley Kennedy</td>
<td>2010/03/17</td> <td>Senior Marketing Designer</td>
<td>$385,750</td> <td>London</td>
</tr> <td>43</td>
<tr> <td>2012/12/18</td>
<td>Michael Silva</td> <td>$313,500</td>
<td>Marketing Designer</td> </tr>
<td>London</td> <tr>
<td>66</td> <td>Tatyana Fitzpatrick</td>
<td>2012/11/27</td> <td>Regional Director</td>
<td>$198,500</td> <td>London</td>
</tr> <td>19</td>
<td>2010/03/17</td>
<td>$385,750</td>
</tr>
<tr>
<td>Michael Silva</td>
<td>Marketing Designer</td>
<td>London</td>
<td>66</td>
<td>2012/11/27</td>
<td>$198,500</td>
</tr>
</tbody> </tbody>
</table> </table>
</div>
</div> </div>
</div> </div>
</div> </div>
</div> }
</div> </div>
</>
</>) )
} }
+4
View File
@@ -8,11 +8,15 @@ const queryKeys = {
recentAction: ['recent-action'], recentAction: ['recent-action'],
settingsData: ['settings_data'], settingsData: ['settings_data'],
myProductConfig: ['myproduct_config'], myProductConfig: ['myproduct_config'],
myTemplateConfig: ['mytemplate_config'],
productTemplateData: ['product_template_data'], productTemplateData: ['product_template_data'],
subscriptions: ['subscriptions'], subscriptions: ['subscriptions'],
profile_data: ['profile_data'], profile_data: ['profile_data'],
my_files: ['my_files'], my_files: ['my_files'],
topics: ['topics'], topics: ['topics'],
payment_report: ['payment_report'],
product_report: ['product_report'],
system_report: ['system_report'],
dashboard: ['dashboard'], dashboard: ['dashboard'],
topBar: ['top-bar'], topBar: ['top-bar'],
+40
View File
@@ -244,6 +244,14 @@ export const getProductColorStyles = (reqData) => {
} }
return postAuxEnd(`/panel/account/products/color-styles`, postData, false) return postAuxEnd(`/panel/account/products/color-styles`, postData, false)
} }
export const getTemplateConfig = (reqData) => {
let postData = {
...reqData,
}
return postAuxEnd(`/panel/myproduct/template-config`, postData, false)
}
// FUNCTION TO ACTIVATE TEMPLATE // FUNCTION TO ACTIVATE TEMPLATE
export const activateTemplate = (reqData) => { export const activateTemplate = (reqData) => {
let postData = { let postData = {
@@ -290,6 +298,14 @@ export const uploadFile = (reqData) => {
return postAuxEnd(`/upload/webfiles`, postData, true) return postAuxEnd(`/upload/webfiles`, postData, true)
} }
// FUNCTION TO CHANGE TEMPLATE MEDIA SET
export const templateMediaSet = (reqData) => {
let postData = {
...reqData,
}
return postAuxEnd(`/panel/myproduct/template-media-set`, postData, false)
}
export const getReportsTopicsList = (reqData) => { export const getReportsTopicsList = (reqData) => {
let postData = { let postData = {
...reqData, ...reqData,
@@ -297,6 +313,30 @@ export const getReportsTopicsList = (reqData) => {
return postAuxEnd(`/panel/report/topics`, postData, false) return postAuxEnd(`/panel/report/topics`, postData, false)
} }
// FUNCTION TO GET PAYMENT REPORTS
export const getPaymentReports = (reqData) => {
let postData = {
...reqData,
}
return postAuxEnd(`/panel/report/item/payment`, postData, false)
}
// FUNCTION TO GET PRODUCT REPORTS
export const getProductReports = (reqData) => {
let postData = {
...reqData,
}
return postAuxEnd(`/panel/report/item/product`, postData, false)
}
// FUNCTION TO GET SYSTEM REPORTS
export const getSystemReports = (reqData) => {
let postData = {
...reqData,
}
return postAuxEnd(`/panel/report/item/system`, postData, false)
}
// FUNCTION TO GET COMMON PRACTICE // FUNCTION TO GET COMMON PRACTICE
export const getCommonPractice = (reqData) => { export const getCommonPractice = (reqData) => {
let postData = { let postData = {