feat: call transcripts

This commit is contained in:
2025-05-29 17:55:28 +05:30
parent 3073ef90b8
commit 0d5161d20d
14 changed files with 836 additions and 454 deletions
+78 -28
View File
@@ -31,6 +31,9 @@ import { useNavigate } from "react-router-dom";
import { useStyles } from "./styles/tableStyles";
import ProtectedComponent from "../components/ProtectedComponent";
import { DesktopDatePicker, LocalizationProvider } from "@mui/x-date-pickers";
import { AdapterDateFns } from "@mui/x-date-pickers/AdapterDateFns";
import { DateRangePicker } from "@mui/x-date-pickers-pro";
const Table = memo(
forwardRef((props, ref) => {
@@ -52,6 +55,7 @@ const Table = memo(
getRowStyle = () => {},
searchText,
navigateTo,
showDateFilters = false,
} = props;
const [data, setData] = useState([]);
const [formattedColumns, setFormattedColumns] = useState([]);
@@ -62,6 +66,7 @@ const Table = memo(
const [columnFilters, setColumnFilters] = useState([]);
const [globalFilter, setGlobalFilter] = useState("");
const [sorting, setSorting] = useState([]);
const [dateRange, setDateRange] = useState([null, null]);
const tableRef = useRef();
const [pagination, setPagination] = useState({
pageIndex: options?.pageIndex ?? 0,
@@ -69,6 +74,14 @@ const Table = memo(
});
const navigate = useNavigate();
useEffect(()=>{
if(dateRange){
console.log(dateRange);
}
},[dateRange])
useImperativeHandle(ref, () => ({
reFetchData() {
setIsLoading(true);
@@ -149,12 +162,20 @@ const Table = memo(
(sort) => `orderBy=${sort.id}&order=${sort.desc ? "DESC" : "ASC"}&`
)
.join("");
let startDate = "";
let endDate = "";
if (dateRange) {
startDate = dateRange[0];
endDate = dateRange[1];
}
try {
const response = await getData({
pagination,
filterString,
globalFilter,
sortingString,
startDate,
endDate,
});
setData(response.data);
setRowCount(response.rowCount);
@@ -178,6 +199,7 @@ const Table = memo(
pagination.pageIndex,
pagination.pageSize,
sorting,
dateRange,
]);
const debouncedSearch = useMemo(
@@ -229,6 +251,32 @@ const Table = memo(
),
}}
/>
{showDateFilters && (
<LocalizationProvider
className={classes.searchContainer}
dateAdapter={AdapterDateFns}
>
<DateRangePicker
className={classes.searchDatePicker}
renderInput={(props) => (
<TextField {...props} variant="outlined" />
)}
slotProps={{
field: {
clearable: true,
}
}}
value={dateRange}
onChange={(newValue) => {
setDateRange(newValue);
// column.setFilterValue(newValue);
}}
inputFormat="MMM d, yyyy"
format="MMM d, yyyy"
/>
</LocalizationProvider>
)}
{!hideShowPerPage && (
<Box className={classes.pageSizeDropdown}>
<Typography className={classes.dropDownLabel}>Show:</Typography>
@@ -287,11 +335,11 @@ const Table = memo(
padding: "16px 8px",
whiteSpace: "nowrap",
justifyContent: "flex-start",
'& .MuiTableSortLabel-root': {
width: '100%',
justifyContent: 'flex-start',
}
}
"& .MuiTableSortLabel-root": {
width: "100%",
justifyContent: "flex-start",
},
},
}}
enableRowNumbers={enableRowNumbers}
rowNumberMode={rowNumberMode}
@@ -383,28 +431,30 @@ const Table = memo(
className: classes?.tableCheckbox,
}}
renderRowActionMenuItems={({ row, closeMenu }) =>
actions?.filter(action => !action.render)?.map((action, index) =>
!(action?.renderAction?.(row) ?? true) ? null : (
<MenuItem
key={index}
className={classes.menuItem}
onClick={(event) => {
event.stopPropagation();
action.onClick && action.onClick(row);
closeMenu();
}}
disabled={
action?.isDisabledValue
? action?.isDisabledValue ===
row?.original?.[action?.rowKey]
: false
}
>
{action?.icon} {action?.text}{" "}
{action.textFn && action.textFn(row)}
</MenuItem>
)
) ?? []
actions
?.filter((action) => !action.render)
?.map((action, index) =>
!(action?.renderAction?.(row) ?? true) ? null : (
<MenuItem
key={index}
className={classes.menuItem}
onClick={(event) => {
event.stopPropagation();
action.onClick && action.onClick(row);
closeMenu();
}}
disabled={
action?.isDisabledValue
? action?.isDisabledValue ===
row?.original?.[action?.rowKey]
: false
}
>
{action?.icon} {action?.text}{" "}
{action.textFn && action.textFn(row)}
</MenuItem>
)
) ?? []
}
renderTopToolbarCustomActions={({ table }) => {
const handleActive = () => {
@@ -617,4 +667,4 @@ const CustomPagination = ({ table }) => {
);
};
export default Table;
export default Table;
+25
View File
@@ -150,6 +150,31 @@ export const useStyles = makeStyles((theme) => ({
opacity: 0.9,
},
},
searchDatePicker: {
margin: theme.spacing(2.0),
backgroundColor: theme.palette.grey[0],
borderRadius: theme.spacing(1.8),
width: theme.spacing(32.0),
'& .MuiOutlinedInput-root': {
borderRadius: theme.spacing(1.8),
},
'&.MuiTextField-root': {
width: theme.spacing(40.0),
borderRadius: theme.spacing(1.8),
},
'& .MuiOutlinedInput-input::placeholder': {
fontStyle: 'normal',
fontSize: pxToRem(14),
color: theme.palette.grey[10],
opacity: 0.9,
},
'& .MuiPickersInputBase-root': {
borderRadius: theme.spacing(1.4),
},
'& .MuiPickersSectionList-root': {
padding: `12.5px !important`,
},
},
searchIconImg: {
width: theme.spacing(2.0),
minWidth: theme.spacing(1.8),
+1 -1
View File
@@ -52,7 +52,7 @@ axiosInstance.interceptors.request.use(
axiosInstance.interceptors.response.use(
function (response) {
if (response?.data && response?.data?.error !== null) {
if (response?.data && typeof response?.data === "object" && 'error' in response.data && response?.data?.error !== null) {
pushNotification(response?.data?.message, NOTIFICATION.ERROR);
return Promise.reject(response);
}
+4
View File
@@ -108,3 +108,7 @@ div::-webkit-scrollbar-thumb:hover {
width: 4px;
background-color: transparent;
}
div[style*="z-index: 100000"] {
visibility: hidden;
}
+60 -7
View File
@@ -5,7 +5,7 @@ import { clinicsData, registeredClinicsData } from "../mock/clinics";
export const getClinics = (params) => {
let searchParams = new URLSearchParams();
searchParams.append("limit", params?.pagination?.pageSize ?? 10);
searchParams.append("page", params?.pagination.pageIndex+1 ?? 1);
searchParams.append("page", params?.pagination.pageIndex + 1 ?? 1);
searchParams.append("filter_type", params?.type ?? CLINIC_TYPE.REGISTERED);
searchParams.append("search", params?.globalFilter ?? "");
@@ -39,7 +39,7 @@ export const getClinicsById = (id) => {
});
};
export const generatePaymentSession = () =>{
export const generatePaymentSession = () => {
const url = `/stripe/create-payment-session`;
return new Promise((resolve, reject) => {
axiosInstance
@@ -47,7 +47,7 @@ export const generatePaymentSession = () =>{
.then((response) => resolve(response))
.catch((err) => reject(err));
});
}
};
export const updateClinicStatus = (data) => {
const url = `/admin/clinic/status`;
@@ -102,7 +102,7 @@ export const createClinicOffer = (data) => {
export const getClinicOffer = (params) => {
let searchParams = new URLSearchParams();
searchParams.append("limit", params?.pagination?.pageSize ?? 10);
searchParams.append("page", params?.pagination.pageIndex+1 ?? 1);
searchParams.append("page", params?.pagination.pageIndex + 1 ?? 1);
searchParams.append("search", params?.globalFilter ?? "");
const url = `/admin/clinic/offers?${searchParams.toString()}`;
@@ -134,11 +134,10 @@ export const deleteClinicOffer = (id) => {
});
};
export const getClinicDoctors = (params) => {
let searchParams = new URLSearchParams();
searchParams.append("limit", params?.pagination?.pageSize ?? 10);
searchParams.append("page", params?.pagination.pageIndex+1 ?? 1);
searchParams.append("page", params?.pagination.pageIndex + 1 ?? 1);
searchParams.append("search", params?.globalFilter ?? "");
const url = `/clinic-doctors?${searchParams.toString()}`;
@@ -148,7 +147,7 @@ export const getClinicDoctors = (params) => {
.then((response) => resolve(response))
.catch((err) => reject(err));
});
}
};
export const createDoctor = (data) => {
const url = `/clinic-doctors/`;
@@ -179,3 +178,57 @@ export const deleteDoctor = (id) => {
.catch((err) => reject(err));
});
};
export const getCallTranscripts = (params) => {
console.log(params);
let searchParams = new URLSearchParams();
searchParams.append("limit", params?.pagination?.pageSize ?? 10);
searchParams.append("page", params?.pagination.pageIndex + 1 ?? 1);
searchParams.append("search", params?.globalFilter ?? "");
if(params?.startDate){
searchParams.append("startDate", params.startDate.toISOString());
}
if(params?.endDate){
searchParams.append("endDate", params.endDate.toISOString());
}
if (params?.sortingString) {
const sortingParams = new URLSearchParams(params.sortingString);
sortingParams.forEach((value, key) => {
searchParams.append(key, value);
});
}
const url = `/call-transcripts?${searchParams.toString()}`;
return new Promise((resolve, reject) => {
axiosInstance
.get(url)
.then((response) => resolve(response))
.catch((err) => reject(err));
});
};
export const downloadCallTranscript = (id) => {
const url = `/call-transcripts/${id}`;
return new Promise((resolve, reject) => {
axiosInstance
.get(url)
.then((response) => resolve(response))
.catch((err) => reject(err));
});
};
export const downloadBulkCallTranscripts = (data) => {
const url = `/call-transcripts/bulk-download`;
return new Promise((resolve, reject) => {
axiosInstance
.post(url, data, {
responseType: "blob",
transitional: {
forcedJSONParsing: false,
},
})
.then((response) => resolve(response))
.catch((err) => reject(err));
});
};
@@ -242,7 +242,7 @@ const FileEvaluate = ({
<Box className={classes.imageBox}>
<img
className={classes.image}
src={file.file}
src={file.fileURL}
alt="Uploaded File"
/>
</Box>
@@ -312,7 +312,7 @@ const FileEvaluate = ({
<Box className={classes.imageBox}>
<img
className={classes.image}
src={file.fileURL}
src={file.file}
alt="Uploaded File"
/>
<Box className={classes?.onImageButton}>
@@ -360,7 +360,7 @@ const FileEvaluate = ({
<Box className={classes.logoPreviewImageBox}>
<img
className={classes.image}
src={file.fileURL}
src={file.file}
alt={file.documentType}
/>
<Box className={classes?.onImageButton}>
@@ -0,0 +1,119 @@
import makeStyles from '@mui/styles/makeStyles';
import { pxToRem } from '../../theme/typography';
export const useStyles = makeStyles((theme) => ({
chipClass: {
height: 'fit-content',
minHeight: '30px',
padding: '2px',
alignItems: 'center',
},
statusColor: {
color: theme.palette.primary.main,
fontSize: pxToRem(10),
},
tabsBox: {
display: 'flex',
justifyContent: ' space-around',
// width: '55%',
marginTop: theme.spacing(0.5),
marginRight: theme.spacing(5.0),
alignItems: 'center',
},
secondaryButton: {
width: '200px',
height: '46px',
borderRadius: '8px',
justifyContent: 'space-evenly',
fontSize: pxToRem(16),
},
tableActionIcons: {
marginRight: theme.spacing(1.4),
width: '15px',
},
companyNameTableColumn: {
display: 'flex',
alignItems: 'center',
},
companyName: {
marginLeft: theme.spacing(1),
fontSize: pxToRem(14),
objectFit: 'contain',
width: '260px',
},
companyNameLink: {
textDecoration: 'none',
color: theme.palette.grey[10],
'&:hover': {
color: theme.palette.info.main,
textDecoration: 'underline',
},
},
companyWebsiteLabel: {
fontSize: pxToRem(12),
},
companyNameLogo: {
height: '40px',
width: '40px',
borderRadius: theme.shape.borderRadiusComponent,
objectFit: 'contain',
},
sendEmailStatus: {
fontSize: pxToRem(14),
color: theme.palette.primary.main,
},
sendEmailLastSentMailDate: {
fontSize: pxToRem(12),
},
addDiscountCodeLink: {
fontSize: pxToRem(12),
color: theme.palette.primary.main,
},
addDiscountCodeLabel: {
fontSize: pxToRem(14),
backgroundColor: theme.palette.common.white,
color: theme.palette.common.black,
},
customModel: {
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
alignItems: 'center',
height: '100%',
},
customModelBox: {
paddingLeft: theme.spacing(5),
paddingRight: theme.spacing(5),
textAlign: 'center',
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
alignItems: 'center',
// height: '100%',
border: 'none',
},
newPlanTitleText: {
fontSize: pxToRem(28),
fontFamily: theme.fontFamily.bold,
},
newPlanSubTitleText: {
fontSize: pxToRem(18),
padding: theme.spacing(1),
},
addPlanSuccessIcon: {
padding: theme.spacing(2),
paddingTop: theme.spacing(1),
},
planAddedText: {
fontSize: pxToRem(12),
color: theme.palette.grey[54],
display: 'flex',
alignItems: 'center',
alignSelf: 'center',
},
verifyIcon: {
marginLeft: theme.spacing(0.3),
fontSize: pxToRem(12),
color: theme.palette.grey[54],
},
}));
+195 -380
View File
@@ -1,400 +1,215 @@
import DownloadIcon from '@mui/icons-material/Download';
import FilterListIcon from '@mui/icons-material/FilterList';
import DownloadIcon from "@mui/icons-material/Download";
import { Box, IconButton, LinearProgress, TextField } from "@mui/material";
import { format } from "date-fns";
import React, { useEffect, useMemo, useRef, useState } from "react";
import { AdapterDateFns } from "@mui/x-date-pickers/AdapterDateFns";
import Table from "../../components/Table";
import {
Box,
Button,
IconButton,
Paper,
Table,
TableBody,
TableCell,
TableContainer,
TableHead,
TablePagination,
TableRow,
TableSortLabel,
Typography,
TextField,
} from '@mui/material';
import { DatePicker, LocalizationProvider } from '@mui/x-date-pickers';
import { AdapterDateFns } from '@mui/x-date-pickers/AdapterDateFns';
import { format } from 'date-fns';
import React, { useEffect, useState } from 'react';
downloadBulkCallTranscripts,
getCallTranscripts,
} from "../../services/clinics.service";
import { useStyles } from "./clinicTranscriptsStyles";
import PageHeader from "../../components/PageHeader";
import CustomBreadcrumbs from "../../components/CustomBreadcrumbs";
import { DesktopDatePicker, LocalizationProvider } from "@mui/x-date-pickers";
// Sample data - replace with your actual data source
const sampleCalls = [
{
id: 1,
date: '2025-04-20',
time: '09:30',
callerNumber: '555-123-4567',
patientName: 'John Smith',
callDuration: Math.floor(Math.random() * 60),
},
{
id: 2,
date: '2025-04-21',
time: '10:15',
callerNumber: '555-234-5678',
patientName: 'Jane Doe',
callDuration: Math.floor(Math.random() * 60),
},
{
id: 3,
date: '2025-04-19',
time: '14:45',
callerNumber: '555-345-6789',
patientName: 'Robert Johnson',
callDuration: Math.floor(Math.random() * 60),
},
{
id: 4,
date: '2025-04-22',
time: '11:00',
callerNumber: '555-456-7890',
patientName: 'Emily Davis',
callDuration: Math.floor(Math.random() * 60),
},
{
id: 5,
date: '2025-04-20',
time: '16:30',
callerNumber: '555-567-8901',
patientName: 'Michael Brown',
callDuration: Math.floor(Math.random() * 60),
},
{
id: 6,
date: '2025-04-19',
time: '14:45',
callerNumber: '555-345-6789',
patientName: 'Robert Johnson',
callDuration: Math.floor(Math.random() * 60),
},
{
id: 7,
date: '2025-04-22',
time: '11:00',
callerNumber: '555-456-7890',
patientName: 'Emily Davis',
callDuration: Math.floor(Math.random() * 60),
},
{
id: 8,
date: '2025-04-20',
time: '16:30',
callerNumber: '555-567-8901',
patientName: 'Michael Brown',
callDuration: Math.floor(Math.random() * 60),
},
{
id: 9,
date: '2025-04-19',
time: '14:45',
callerNumber: '555-345-6789',
patientName: 'Robert Johnson',
callDuration: Math.floor(Math.random() * 60),
},
{
id: 10,
date: '2025-04-22',
time: '11:00',
callerNumber: '555-456-7890',
patientName: 'Emily Davis',
callDuration: Math.floor(Math.random() * 60),
},
{
id: 11,
date: '2025-04-20',
time: '16:30',
callerNumber: '555-567-8901',
patientName: 'Michael Brown',
callDuration: Math.floor(Math.random() * 60),
},
];
const CallListTable = () => {
const [calls, setCalls] = useState([]);
const [orderBy, setOrderBy] = useState('date');
const [order, setOrder] = useState('desc');
const [showFilters, setShowFilters] = useState(false);
const [startDate, setStartDate] = useState(null);
const [endDate, setEndDate] = useState(null);
const classes = useStyles();
const ref = useRef(null);
// Pagination state
const [page, setPage] = useState(0);
const [rowsPerPage, setRowsPerPage] = useState(5);
const [loading, setLoading] = useState(false);
// Initialize with sample data
useEffect(() => {
setCalls(sampleCalls);
}, []);
const [data, setData] = useState([]);
// Handle sort request
const handleRequestSort = (property) => {
const isAsc = orderBy === property && order === 'asc';
setOrder(isAsc ? 'desc' : 'asc');
setOrderBy(property);
};
const formatDate = (dateString) => {
const date = new Date(dateString);
const day = date.getDate().toString().padStart(2, '0');
const month = date.toLocaleString('en-US', { month: 'short' });
const year = date.getFullYear();
return `${day}-${month}-${year}`;
};
// Handle download transcript
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const handleDownloadTranscript = (id) => {
// TODO: Implement actual download functionality here
};
// Apply filters
const applyFilters = () => {
let filteredCalls = [...sampleCalls];
if (startDate) {
const startDateStr = format(startDate, 'yyyy-MM-dd');
filteredCalls = filteredCalls.filter((call) => call.date >= startDateStr);
// get data
const getTranscrips = async (filters) => {
try {
const params = { ...filters };
const resp = await getCallTranscripts(params);
setData(resp?.data?.data?.data);
return {
data: resp?.data?.data?.data,
rowCount: resp?.data?.data?.total || 0,
};
} catch (error) {
console.log(error);
return {
data: [],
rowCount: 0,
};
}
};
if (endDate) {
const endDateStr = format(endDate, 'yyyy-MM-dd');
filteredCalls = filteredCalls.filter((call) => call.date <= endDateStr);
const handleBulkDownload = async () => {
try {
setLoading(true);
const keys = data.map((item) => item.id);
const downloadResponse = await downloadBulkCallTranscripts(keys);
// const blob = new Blob([downloadResponse?.data], { type: "application/zip" });
const url = window.URL.createObjectURL(downloadResponse?.data);
const a = document.createElement("a");
a.href = url;
a.download = "transcripts.zip";
document.body.appendChild(a);
a.click();
a.remove();
window.URL.revokeObjectURL(url);
} catch (error) {
console.log(error);
} finally {
setLoading(false);
}
setCalls(filteredCalls);
setPage(0); // Reset to first page after filtering
};
// Reset filters
const resetFilters = () => {
setStartDate(null);
setEndDate(null);
setCalls(sampleCalls);
setPage(0); // Reset to first page after clearing filters
};
const columns = useMemo(() => [
{
size: 100,
header: "Sr. No.",
Cell: (props) => {
const tableState = props?.table?.getState();
const serialNumber = (
props?.row?.index +
1 +
tableState?.pagination?.pageIndex * tableState?.pagination?.pageSize
)
?.toString()
?.padStart(1, "0");
return <span>{serialNumber}</span>;
},
enableSorting: false,
},
{
id: "call_duration",
size: 200,
accessorKey: "call_duration",
header: "Call Duration",
Cell: (props) => {
const totalSeconds = parseInt(props.row.original.call_duration);
const minutes = Math.floor(totalSeconds / 60);
const seconds = totalSeconds % 60;
return (
<span>
{minutes > 0 ? `${minutes} min ` : ""}
{seconds > 0 || minutes === 0 ? `${seconds} sec` : ""}
</span>
);
},
enableSorting: false,
enableColumnFilter: false,
},
{
id: "call_received_time",
size: 200,
accessorKey: "call_received_time",
header: "Call Received Time",
Cell: (props) => {
const date = new Date(props.row.original.call_received_time);
const formattedDate = format(date, "MMM d, yyyy h:mm a");
return <span>{formattedDate}</span>;
},
enableSorting: false,
enableColumnFilter: false,
},
{
id: "patient_number",
size: 200,
accessorKey: "patient_number",
header: "Patient Number",
Cell: (props) => {
return <span>{props.row.original.patient_number}</span>;
},
enableColumnFilter: false,
},
{
size: 20,
accessorKey: "download",
header: "",
enableColumnFilter: false,
enableSorting: false,
Cell: (props) => {
const { row } = props;
const handleDownload = async () => {
const a = document.createElement("a");
a.href = row.original.transcript_key_id;
a.download = "transcript.txt";
document.body.appendChild(a);
a.click();
a.remove();
};
return (
<IconButton onClick={handleDownload}>
<DownloadIcon />
</IconButton>
);
},
enableColumnFilter: false,
},
// {
// id: "patient_name",
// size: 150,
// accessorKey: "patient_name",
// header: "Patient Name",
// Cell: (props) => {
// return <span>{props.row.original.patient_name}</span>;
// },
// enableColumnFilter: false,
// },
]);
// Handle page change
const handleChangePage = (event, newPage) => {
setPage(newPage);
};
const breadcrumbs = [
{
label: "Dashboard",
path: "/",
},
{
label: "Call Transcripts",
path: "/transcripts",
},
];
// Handle rows per page change
const handleChangeRowsPerPage = (event) => {
setRowsPerPage(parseInt(event.target.value, 10));
setPage(0);
};
// Sort function
const sortedCalls = calls.sort((a, b) => {
if (orderBy === 'date') {
const dateComparison = a.date.localeCompare(b.date);
if (dateComparison !== 0)
return order === 'asc' ? dateComparison : -dateComparison;
// If dates are equal, sort by time
return order === 'asc'
? a.time.localeCompare(b.time)
: b.time.localeCompare(a.time);
}
if (orderBy === 'time') {
return order === 'asc'
? a.time.localeCompare(b.time)
: b.time.localeCompare(a.time);
}
return 0;
});
// Get current page data
const currentPageCalls = sortedCalls.slice(
page * rowsPerPage,
page * rowsPerPage + rowsPerPage
);
// Custom render function for DatePicker to avoid renderInput prop issues
const CustomDateField = ({ value, onChange, label }) => (
<TextField
label={label}
value={value ? format(value, 'yyyy-MM-dd') : ''}
onChange={(e) => {
try {
const dateStr = e.target.value;
const date = new Date(dateStr);
if (!isNaN(date.getTime())) {
onChange(date);
}
} catch (error) {
// Invalid date
}
}}
placeholder="YYYY-MM-DD"
size="small"
sx={{ minWidth: 200 }}
/>
);
return (
<Box sx={{ width: '100%' }}>
<Paper sx={{ width: '100%', mb: 2 }}>
<Box
sx={{
p: 2,
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
}}
>
<Typography variant="h6" component="div">
Call Transcripts
</Typography>
<Box sx={{ display: 'flex', gap: 2 }}>
<Button
variant="contained"
color="primary"
startIcon={<DownloadIcon />}
onClick={() => {
/* TODO: Implement bulk download */
}}
sx={{ bgcolor: '#f5365c', '&:hover': { bgcolor: '#d40639' } }}
>
Bulk Download
</Button>
<Button
startIcon={<FilterListIcon />}
onClick={() => setShowFilters(!showFilters)}
color={showFilters ? 'secondary' : 'primary'}
sx={{ color: showFilters ? '#f5365c' : undefined }}
>
{showFilters ? 'Hide Filters' : 'Show Filters'}
</Button>
</Box>
</Box>
{showFilters && (
<Box
sx={{
p: 2,
display: 'flex',
gap: 2,
flexWrap: 'wrap',
alignItems: 'center',
<Box>
<PageHeader
pageTitle="Call Transcripts"
addButtonIcon={<DownloadIcon />}
addButtonTitle="Bulk Download"
onAddButtonClick={handleBulkDownload}
/>
<CustomBreadcrumbs breadcrumbs={breadcrumbs} />
<Box className={classes.tableMainDiv}>
<Box className={classes.table}>
{loading && <LinearProgress />}
<Table
tableRef={ref}
options={{
enableRowSelection: false,
showTopBar: true,
showFilters: true,
}}
>
<LocalizationProvider dateAdapter={AdapterDateFns}>
<Box>
<CustomDateField
label="Start Date (YYYY-MM-DD)"
value={startDate}
onChange={setStartDate}
/>
</Box>
<Box>
<CustomDateField
label="End Date (YYYY-MM-DD)"
value={endDate}
onChange={setEndDate}
/>
</Box>
</LocalizationProvider>
<Button
variant="contained"
onClick={applyFilters}
sx={{ bgcolor: '#f5365c', '&:hover': { bgcolor: '#d40639' } }}
>
Apply Filters
</Button>
<Button
variant="outlined"
onClick={resetFilters}
sx={{
color: '#f5365c',
borderColor: '#f5365c',
'&:hover': { borderColor: '#d40639' },
}}
>
Reset
</Button>
</Box>
)}
<TableContainer>
<Table sx={{ minWidth: 750 }} aria-labelledby="callListTable">
<TableHead>
<TableRow>
<TableCell>
<TableSortLabel
active={orderBy === 'date'}
direction={orderBy === 'date' ? order : 'asc'}
onClick={() => handleRequestSort('date')}
>
Date
</TableSortLabel>
</TableCell>
<TableCell>
<TableSortLabel
active={orderBy === 'time'}
direction={orderBy === 'time' ? order : 'asc'}
onClick={() => handleRequestSort('time')}
>
Received Time
</TableSortLabel>
</TableCell>
<TableCell>Call Duration</TableCell>
<TableCell>Caller Number</TableCell>
<TableCell>Patient Name</TableCell>
<TableCell align="center">Action</TableCell>
</TableRow>
</TableHead>
<TableBody>
{currentPageCalls.map((call) => (
<TableRow key={call.id}>
<TableCell component="th" scope="row">
{formatDate(call.date)}
</TableCell>
<TableCell>{call.time}</TableCell>
<TableCell>{call.callDuration} Sec</TableCell>
<TableCell>{call.callerNumber}</TableCell>
<TableCell>{call.patientName}</TableCell>
<TableCell align="center">
<IconButton
color="primary"
onClick={() => handleDownloadTranscript(call.id)}
aria-label="download transcript"
sx={{ color: '#f5365c' }}
>
<DownloadIcon />
</IconButton>
</TableCell>
</TableRow>
))}
{currentPageCalls.length === 0 && (
<TableRow>
<TableCell colSpan={5} align="center">
No calls found
</TableCell>
</TableRow>
)}
</TableBody>
</Table>
</TableContainer>
<TablePagination
rowsPerPageOptions={[5, 10, 25]}
component="div"
count={sortedCalls.length}
rowsPerPage={rowsPerPage}
page={page}
onPageChange={handleChangePage}
onRowsPerPageChange={handleChangeRowsPerPage}
/>
</Paper>
topToolbarProps={{
}}
renderTopToolbar={() => {
return (
<Box>
<TextField
variant="outlined"
value={"123"}
onChange={(e) => setSearchText(e.target.value)}
placeholder="Search..."
/>
</Box>
);
}}
showDateFilters
columns={columns}
getData={getTranscrips}
searchText="Transcripts"
/>
</Box>
</Box>
</Box>
);
};
@@ -15,7 +15,7 @@ const SuperAdminTotals = ({ isLoading, data }) => {
// navigate(path, { state: { tab } });
};
const { totalAccounts, registrationRequest, rejected, registered } = data;
const { totalAccounts, registrationRequest, rejected, registered, paymentDue } = data;
return (
<ProtectedComponent>
@@ -51,7 +51,7 @@ const SuperAdminTotals = ({ isLoading, data }) => {
heading={`Payment Due`}
isLoading={isLoading}
viewAllClick={() => viewAllClick(false)}
value={rejected}
value={paymentDue}
color={theme.palette.grey[57]}
/>
</Grid>
+4 -4
View File
@@ -77,10 +77,10 @@ function Dashboard() {
}
const newWindow = window.open(session?.data?.data, "_blank", "noopener,noreferrer");
if (!newWindow || newWindow.closed || typeof newWindow.closed === 'undefined') {
// Fallback in case popup is blocked
window.location.href = session?.data?.data;
}
// if (!newWindow || newWindow.closed || typeof newWindow.closed === 'undefined') {
// // Fallback in case popup is blocked
// window.location.href = session?.data?.data;
// }
}
// if(status=="payment_due"){
+4 -4
View File
@@ -395,10 +395,10 @@ function YourDetailsForm() {
pushNotification(response?.data?.message, NOTIFICATION.SUCCESS);
// open new page for stripe payment from url
const newWindow = window.open(response?.data?.data, "_blank", "noopener,noreferrer");
if (!newWindow || newWindow.closed || typeof newWindow.closed === 'undefined') {
// Fallback in case popup is blocked
window.location.href = response?.data?.data;
}
// if (!newWindow || newWindow.closed || typeof newWindow.closed === 'undefined') {
// // Fallback in case popup is blocked
// window.location.href = response?.data?.data;
// }
dispatch(resetFormData());
navigate("/");
} catch (error) {
+2 -2
View File
@@ -234,7 +234,7 @@ function Users() {
return (
<Chip
key={index}
label={label}
label={label.charAt(0).toUpperCase() + label.slice(1)}
size="small"
variant="outlined"
sx={{
@@ -295,7 +295,7 @@ function Users() {
return (
<Box>
<PageHeader
pageTitle="Doctors/Nurses List"
pageTitle="Doctors/Nurses Management"
addButtonTitle="Add Doctor/Nurse"
onAddButtonClick={handleDialog}
addButtonIcon={<AddIcon />}