2024-02-16 11:09:15 +00:00
import { t } from '@lingui/macro' ;
2024-02-22 02:03:15 +00:00
import { Button , Input , Table , Tag , DatePicker , Form , Modal , Select , Space , Spin , message } from 'antd' ;
import React , { useContext , useEffect , useRef , useState } from 'react' ;
import type { GetRef } from 'antd' ;
2024-02-16 11:09:15 +00:00
import { Layout } from 'antd' ;
2024-02-20 08:01:06 +00:00
import {
2024-02-22 03:43:14 +00:00
DownloadOutlined , CheckCircleOutlined ,
2024-02-20 08:01:06 +00:00
ArrowLeftOutlined ,
ArrowRightOutlined ,
FullscreenOutlined ,
FullscreenExitOutlined ,
2024-02-22 09:36:03 +00:00
ClockCircleFilled ,
2024-02-20 08:01:06 +00:00
} from '@ant-design/icons' ;
import styled from 'styled-components' ;
2024-02-16 11:09:15 +00:00
const { Sider , Content } = Layout ;
2024-02-21 11:11:02 +00:00
import { baseURL } from "request/api" ;
2024-02-22 09:36:03 +00:00
import { useHotkeys } from "react-hotkeys-hook" ;
2024-03-06 04:43:11 +00:00
// Import the main component
import { Viewer } from '@react-pdf-viewer/core' ;
// Import the styles
import '@react-pdf-viewer/core/lib/styles/index.css' ;
2024-01-31 04:08:20 +00:00
2024-02-22 02:03:15 +00:00
2024-02-16 11:09:15 +00:00
const siderStyle : React.CSSProperties = {
backgroundColor : '#fafafa' ,
padding : 10 ,
width : 200 ,
} ;
2024-02-20 08:01:06 +00:00
const StyledTable = styled ( Table ) `
& . sbt - table - cell {
padding : 4px ! important ;
}
` ;
2024-02-22 02:03:15 +00:00
type InputRef = GetRef < typeof Input > ;
type FormInstance < T > = GetRef < typeof Form < T > > ;
const EditableContext = React . createContext < FormInstance < any > | null > ( null ) ;
interface Item {
key : string ;
accuracy : number ;
submitted : string ;
revised : string ;
action : string ;
}
interface EditableRowProps {
index : number ;
}
const EditableRow : React.FC < EditableRowProps > = ( { index , . . . props } ) = > {
const [ form ] = Form . useForm ( ) ;
return (
< Form form = { form } component = { false } >
< EditableContext.Provider value = { form } >
< tr { ...props } / >
< / EditableContext.Provider >
< / Form >
) ;
} ;
interface EditableCellProps {
title : React.ReactNode ;
editable : boolean ;
children : React.ReactNode ;
dataIndex : keyof Item ;
record : Item ;
handleSave : ( record : Item ) = > void ;
}
const EditableCell : React.FC < EditableCellProps > = ( {
title ,
editable ,
children ,
dataIndex ,
record ,
handleSave ,
. . . restProps
} ) = > {
const [ editing , setEditing ] = useState ( false ) ;
const inputRef = useRef < InputRef > ( null ) ;
const form = useContext ( EditableContext ) ! ;
useEffect ( ( ) = > {
if ( editing ) {
inputRef . current ! . focus ( ) ;
}
} , [ editing ] ) ;
const toggleEdit = ( ) = > {
setEditing ( ! editing ) ;
form . setFieldsValue ( { [ dataIndex ] : record [ dataIndex ] } ) ;
} ;
const save = async ( ) = > {
try {
const values = await form . validateFields ( ) ;
toggleEdit ( ) ;
handleSave ( { . . . record , . . . values } ) ;
} catch ( errInfo ) {
console . log ( 'Save failed:' , errInfo ) ;
}
} ;
let childNode = children ;
if ( editable ) {
childNode = editing ? (
< Form.Item
style = { { margin : 0 } }
name = { dataIndex }
rules = { [
{
required : true ,
message : ` ${ title } is required. ` ,
} ,
] }
>
< Input ref = { inputRef } onPressEnter = { save } onBlur = { save } / >
< / Form.Item >
) : (
< div className = "editable-cell-value-wrap" style = { { paddingRight : 24 } } onClick = { toggleEdit } >
{ children }
< / div >
) ;
}
return < td { ...restProps } > { childNode } < / td > ;
} ;
2024-02-22 03:43:14 +00:00
// type EditableTableProps = Parameters<typeof Table>[0];
2024-02-20 08:01:06 +00:00
2024-02-22 09:36:03 +00:00
const FileCard = ( { file , isSelected , onClick , setIsReasonModalOpen } ) = > {
2024-02-21 11:11:02 +00:00
const fileName = file [ "File Name" ] ;
2024-02-16 11:09:15 +00:00
return (
< div style = { {
border : '1px solid #ccc' ,
width : '200px' ,
2024-02-19 04:02:21 +00:00
backgroundColor : isSelected ? '#d4ecff' : '#fff' ,
2024-02-16 11:09:15 +00:00
padding : '4px 8px' ,
marginRight : '4px' ,
2024-02-20 08:01:06 +00:00
marginTop : '2px' ,
position : 'relative' ,
height : '100px' ,
2024-02-22 09:36:03 +00:00
overflow : 'hidden' ,
2024-02-16 11:09:15 +00:00
} } onClick = { onClick } >
< div >
< span style = { {
fontSize : '12px' ,
color : '#333' ,
fontWeight : 'bold' ,
padding : '4px 8px' ,
2024-02-20 08:01:06 +00:00
cursor : 'default' ,
2024-02-21 11:11:02 +00:00
} } > { file [ "Doc Type" ] . toUpperCase ( ) } < / span >
2024-02-16 11:09:15 +00:00
< span style = { {
fontSize : '12px' ,
color : '#aaa' ,
fontWeight : 'bold' ,
padding : '4px 8px' ,
2024-02-20 08:01:06 +00:00
cursor : 'default' ,
2024-02-21 11:11:02 +00:00
maxWidth : '50px' ,
overflow : 'hidden' ,
textOverflow : 'ellipsis' ,
} } >
2024-02-21 12:01:19 +00:00
{ fileName ? fileName . substring ( 0 , 25 ) . replace ( "temp_" , "" ) : fileName }
2024-02-21 11:11:02 +00:00
< / span >
2024-02-16 11:09:15 +00:00
< / div >
2024-02-20 08:01:06 +00:00
< div style = { {
padding : '4px' ,
position : 'absolute' ,
bottom : 2 ,
right : 2 ,
} } >
< Button style = { {
margin : '4px 2px' ,
2024-02-22 09:36:03 +00:00
} }
onClick = { ( ) = > {
setIsReasonModalOpen ( true ) ;
} }
>
2024-02-20 08:01:06 +00:00
Review
< / Button >
< Button style = { {
margin : '4px 2px' ,
2024-02-21 12:01:19 +00:00
} } onClick = { ( ) = > {
const downloadUrl = file [ "File URL" ] ;
window . open ( downloadUrl , '_blank' ) ;
2024-02-20 08:01:06 +00:00
} } >
< DownloadOutlined / >
< / Button >
< / div >
2024-02-16 11:09:15 +00:00
< / div >
) ;
} ;
2024-02-21 12:01:19 +00:00
const fetchAllRequests = async ( filterDateRange , filterSubsidiaries , filterReviewState , filterIncludeTests , page = 1 , page_size = 20 ) = > {
2024-02-22 09:36:03 +00:00
const startDate = ( filterDateRange && filterDateRange [ 0 ] ) ? filterDateRange [ 0 ] : '' ;
const endDate = ( filterDateRange && filterDateRange [ 1 ] ) ? filterDateRange [ 1 ] : '' ;
2024-02-21 11:11:02 +00:00
let filterStr = "" ;
filterStr += ` page= ${ page } &page_size= ${ page_size } & ` ;
if ( filterSubsidiaries ) {
filterStr += ` subsidiary= ${ filterSubsidiaries } & ` ;
}
if ( filterReviewState ) {
filterStr += ` is_reviewed= ${ filterReviewState } & ` ;
}
if ( filterIncludeTests ) {
2024-02-22 09:36:03 +00:00
filterStr += ` includes_test= ${ filterIncludeTests } & ` ;
2024-02-21 11:11:02 +00:00
}
if ( startDate && endDate ) {
filterStr += ` start_date= ${ startDate } &end_date= ${ endDate } & ` ;
}
const token = localStorage . getItem ( 'sbt-token' ) || '' ;
const data = await fetch ( ` ${ baseURL } /ctel/request_list/? ${ filterStr } ` , {
method : 'GET' ,
headers : {
"Authorization" : ` ${ JSON . parse ( token ) } `
}
} )
. then ( async ( res ) = > {
const data = await res . json ( ) ;
return data ;
} ) ;
return data ;
} ;
const fetchRequest = async ( id ) = > {
const token = localStorage . getItem ( 'sbt-token' ) || '' ;
const response = await fetch ( ` ${ baseURL } /ctel/request/ ${ id } / ` , {
method : 'GET' ,
headers : {
"Authorization" : ` ${ JSON . parse ( token ) } `
}
} ) ;
return await ( await response . json ( ) ) . subscription_requests [ 0 ] ;
} ;
2024-02-20 08:01:06 +00:00
const ReviewPage = ( ) = > {
2024-02-22 02:03:15 +00:00
const [ loading , setLoading ] = useState ( false ) ;
2024-02-20 08:01:06 +00:00
const [ fullscreen , setFullscreen ] = useState ( false ) ;
const [ isModalOpen , setIsModalOpen ] = useState ( false ) ;
2024-02-22 09:36:03 +00:00
const [ isReasonModalOpen , setIsReasonModalOpen ] = useState ( false ) ;
2024-02-16 11:09:15 +00:00
const [ selectedFileId , setSelectedFileId ] = useState ( 0 ) ;
2024-02-22 03:43:14 +00:00
const [ selectedFileData , setSelectedFileData ] = useState ( null ) ;
2024-02-22 09:36:03 +00:00
const [ selectedFileName , setSelectedFileName ] = useState ( null ) ;
2024-02-21 11:11:02 +00:00
// Default date range: 1 month ago to today
const [ filterDateRange , setFilterDateRange ] = useState ( [
2024-02-22 09:36:03 +00:00
"" , ""
2024-02-21 11:11:02 +00:00
] ) ;
2024-02-23 05:46:32 +00:00
const [ filterSubsidiaries , setFilterSubsidiaries ] = useState ( 'SEAO' ) ;
2024-02-21 11:11:02 +00:00
const [ filterReviewState , setFilterReviewState ] = useState ( 'all' ) ;
const [ filterIncludeTests , setFilterIncludesTests ] = useState ( 'true' ) ;
const [ requests , setRequests ] = useState ( [ ] ) ;
const [ currentRequest , setCurrentRequest ] = useState ( null ) ;
const [ currentRequestIndex , setCurrentRequestIndex ] = useState ( 1 ) ;
const [ hasNextRequest , setHasNextRequest ] = useState ( true ) ;
2024-02-22 09:36:03 +00:00
const [ totalRequests , setTotalPages ] = useState ( 0 ) ;
2024-02-22 02:29:49 +00:00
const [ dataSource , setDataSource ] = useState ( [ ] ) ;
2024-02-21 12:01:19 +00:00
2024-02-22 02:03:15 +00:00
const [ pageIndexToGoto , setPageIndexToGoto ] = useState ( 1 ) ;
2024-02-22 09:36:03 +00:00
const setAndLoadSelectedFile = async ( requestData , index ) = > {
setSelectedFileId ( index ) ;
if ( ! requestData [ "Files" ] [ index ] ) {
setSelectedFileData ( "FAILED_TO_LOAD_FILE" ) ;
return ;
} ;
const fileName = requestData [ "Files" ] [ index ] [ "File Name" ] ;
const fileURL = requestData [ "Files" ] [ index ] [ "File URL" ] ;
const response = await fetch ( fileURL ) ;
if ( response . status === 200 ) {
setSelectedFileName ( fileName ) ;
setSelectedFileData ( fileURL ) ;
console . log ( "Loading file: " + fileName ) ;
console . log ( "URL: " + fileURL ) ;
} else {
setSelectedFileData ( "FAILED_TO_LOAD_FILE" ) ;
}
} ;
2024-03-06 04:43:11 +00:00
const loadCurrentRequest = ( requestIndex ) = > {
2024-02-22 02:03:15 +00:00
setLoading ( true ) ;
2024-03-06 04:43:11 +00:00
fetchAllRequests ( filterDateRange , filterSubsidiaries , filterReviewState , filterIncludeTests , requestIndex , 1 ) . then ( ( data ) = > {
2024-02-21 11:11:02 +00:00
setRequests ( data ? . subscription_requests ) ;
setHasNextRequest ( data ? . subscription_requests . length > 1 ) ;
2024-02-22 09:36:03 +00:00
setTotalPages ( data ? . page ? . total_requests ) ;
2024-02-21 11:11:02 +00:00
const requestData = fetchRequest ( data ? . subscription_requests [ 0 ] . RequestID ) ;
requestData . then ( async ( data ) = > {
if ( data ) setCurrentRequest ( data ) ;
2024-03-12 04:26:50 +00:00
const predicted = ( data && data [ "Predicted Result" ] ) ? data [ "Predicted Result" ] : { } ;
2024-02-22 02:29:49 +00:00
const submitted = ( data && data [ "Feedback Result" ] ) ? data [ "Feedback Result" ] : { } ;
const revised = ( data && data [ "Reviewed Result" ] ) ? data [ "Reviewed Result" ] : { } ;
const keys = Object . keys ( predicted ) ;
const tableRows = [ ] ;
for ( let i = 0 ; i < keys . length ; i ++ ) {
let instance = { } ;
instance [ "key" ] = keys [ i ] ;
instance [ "predicted" ] = predicted [ keys [ i ] ] ;
instance [ "submitted" ] = submitted [ keys [ i ] ] ;
instance [ "revised" ] = revised [ keys [ i ] ] ;
tableRows . push ( instance ) ;
}
setDataSource ( tableRows ) ;
setLoading ( false ) ;
2024-02-22 09:36:03 +00:00
setAndLoadSelectedFile ( data , 0 ) ;
2024-02-22 02:03:15 +00:00
} ) . finally ( ( ) = > {
setLoading ( false ) ;
2024-02-21 11:11:02 +00:00
} ) ;
2024-02-22 02:03:15 +00:00
} ) . finally ( ( ) = > {
setLoading ( false ) ;
2024-02-21 11:11:02 +00:00
} ) ;
} ;
2024-02-22 02:03:15 +00:00
const gotoNextRequest = ( ) = > {
2024-02-22 09:36:03 +00:00
if ( currentRequestIndex >= totalRequests ) {
return ;
}
2024-02-22 02:03:15 +00:00
const nextRequestIndex = currentRequestIndex + 1 ;
setCurrentRequestIndex ( nextRequestIndex ) ;
loadCurrentRequest ( nextRequestIndex ) ;
} ;
2024-02-21 11:11:02 +00:00
const gotoPreviousRequest = ( ) = > {
if ( currentRequestIndex === 1 ) {
return ;
}
const previousRequestIndex = currentRequestIndex - 1 ;
setCurrentRequestIndex ( previousRequestIndex ) ;
2024-02-22 02:03:15 +00:00
loadCurrentRequest ( previousRequestIndex ) ;
2024-02-21 11:11:02 +00:00
} ;
const reloadFilters = ( ) = > {
setCurrentRequestIndex ( 1 ) ;
2024-03-06 04:43:11 +00:00
fetchAllRequests ( filterDateRange , filterSubsidiaries , filterReviewState , filterIncludeTests , 1 , 2 ) . then ( ( data ) = > {
2024-02-22 09:36:03 +00:00
setTotalPages ( data ? . page ? . total_requests ) ;
2024-02-21 11:11:02 +00:00
setRequests ( data ? . subscription_requests ) ;
setHasNextRequest ( data ? . subscription_requests . length > 1 ) ;
const firstRequest = fetchRequest ( data ? . subscription_requests [ 0 ] . RequestID ) ;
firstRequest . then ( async ( data ) = > {
if ( data ) setCurrentRequest ( data ) ;
2024-02-22 09:36:03 +00:00
setAndLoadSelectedFile ( data , 0 ) ;
2024-03-06 04:43:11 +00:00
setTimeout ( ( ) = > {
loadCurrentRequest ( 1 ) ;
} , 500 ) ;
2024-02-21 11:11:02 +00:00
} ) ;
} ) ;
} ;
useEffect ( ( ) = > {
setCurrentRequestIndex ( 1 ) ;
2024-03-06 04:43:11 +00:00
fetchAllRequests ( filterDateRange , filterSubsidiaries , filterReviewState , filterIncludeTests , 1 , 2 ) . then ( ( data ) = > {
2024-02-22 09:36:03 +00:00
setTotalPages ( data ? . page ? . total_requests ) ;
2024-02-21 11:11:02 +00:00
setRequests ( data ? . subscription_requests ) ;
setHasNextRequest ( data ? . subscription_requests . length > 1 ) ;
const firstRequest = fetchRequest ( data ? . subscription_requests [ 0 ] . RequestID ) ;
firstRequest . then ( async ( data ) = > {
if ( data ) setCurrentRequest ( data ) ;
2024-02-22 09:36:03 +00:00
setAndLoadSelectedFile ( data , 0 ) ;
2024-02-21 11:11:02 +00:00
} ) ;
} ) ;
} , [ ] ) ;
2024-02-22 02:03:15 +00:00
const components = {
body : {
row : EditableRow ,
cell : EditableCell ,
} ,
} ;
// "Key", "Accuracy", "Submitted", "Revised"
interface DataType {
key : string ;
accuracy : number ;
submitted : string ;
revised : string ;
} ;
2024-02-22 09:36:03 +00:00
const updateRevisedData = async ( newRevisedData : any ) = > {
2024-02-22 02:29:49 +00:00
const requestID = newRevisedData . request_id ;
const token = localStorage . getItem ( 'sbt-token' ) || '' ;
await fetch ( ` ${ baseURL } /ctel/request/ ${ requestID } / ` , {
method : 'POST' ,
headers : {
"Authorization" : ` ${ JSON . parse ( token ) } ` ,
"Content-Type" : "application/json" ,
} ,
2024-02-22 03:43:14 +00:00
body : JSON.stringify ( {
"reviewed_result" : newRevisedData
} ) ,
2024-02-22 02:29:49 +00:00
} ) . catch ( ( error ) = > {
console . log ( error ) ;
message . error ( "Could not update revised data" ) ;
} ) ;
} ;
2024-02-22 02:03:15 +00:00
const handleSave = ( row : DataType ) = > {
const newData = [ . . . dataSource ] ;
2024-02-22 02:29:49 +00:00
const index = newData . findIndex ( ( item ) = > row . key === item . key ) ;
const item = newData [ index ] ;
newData . splice ( index , 1 , {
. . . item ,
. . . row ,
} ) ;
setDataSource ( newData ) ;
const newRevisedData = { } ;
for ( let i = 0 ; i < newData . length ; i ++ ) {
newRevisedData [ newData [ i ] . key ] = newData [ i ] . revised ;
}
2024-02-22 09:36:03 +00:00
updateRevisedData ( newRevisedData ) . then ( ( ) = > {
// "[Is Reviewed]" => true
setCurrentRequest ( {
. . . currentRequest ,
[ "Is Reviewed" ] : true ,
} )
} )
2024-02-22 02:03:15 +00:00
} ;
2024-03-06 04:43:11 +00:00
const submitRevisedData = async ( ) = > {
const newData = [ . . . dataSource ] ;
const newRevisedData = { } ;
for ( let i = 0 ; i < newData . length ; i ++ ) {
newRevisedData [ newData [ i ] . key ] = newData [ i ] . revised ;
}
console . log ( currentRequest )
updateRevisedData ( newRevisedData ) . then ( ( ) = > {
// "[Is Reviewed]" => true
setCurrentRequest ( {
. . . currentRequest ,
[ "Is Reviewed" ] : true ,
} )
} )
} ;
const defaultColumns = [
{
title : 'Key' ,
dataIndex : 'key' ,
key : 'key' ,
width : 200 ,
} ,
{
title : 'Predicted' ,
dataIndex : 'predicted' ,
key : 'predicted' ,
} ,
{
title : 'Submitted' ,
dataIndex : 'submitted' ,
key : 'submitted' ,
} ,
{
title : ( < div style = { {
width : 120 ,
display : 'flex' ,
lineHeight : '32px' ,
marginLeft : 10 ,
} } > Revised & nbsp ; & nbsp ;
< Button
onClick = { ( ) = > {
if ( ! dataSource || ! dataSource . length ) return ;
setDataSource ( dataSource . map ( item = > {
item . revised = item . predicted ;
return item ;
} ) ) ;
setTimeout ( ( ) = > {
submitRevisedData ( ) ;
} , 1000 ) ;
} }
>
Copy Predicted
< / Button >
< Button
onClick = { ( ) = > {
if ( ! dataSource || ! dataSource . length ) return ;
setDataSource ( dataSource . map ( item = > {
item . revised = item . submitted ;
return item ;
} ) ) ;
setTimeout ( ( ) = > {
submitRevisedData ( ) ;
} , 1000 ) ;
} }
>
Copy Submitted
< / Button >
< / div > ) ,
dataIndex : 'revised' ,
key : 'revised' ,
editable : true ,
render : ( text , record ) = > {
return < div style = { {
color : '#000' ,
fontWeight : 'bold' ,
} } > { text } < / div > ;
} ,
} ,
] ;
2024-02-22 02:03:15 +00:00
const columns = defaultColumns . map ( ( col ) = > {
if ( ! col . editable ) {
return col ;
}
return {
. . . col ,
onCell : ( record : DataType ) = > ( {
record ,
2024-02-22 09:36:03 +00:00
editable : col.key != "request_id" && col . editable ,
2024-02-22 02:03:15 +00:00
dataIndex : col.dataIndex ,
title : col.title ,
handleSave ,
} ) ,
} ;
} ) ;
2024-02-16 11:09:15 +00:00
2024-02-22 09:36:03 +00:00
// use left/right keys to navigate
useHotkeys ( "left" , gotoPreviousRequest ) ;
useHotkeys ( "right" , gotoNextRequest ) ;
const fileExtension = selectedFileName ? selectedFileName . split ( '.' ) . pop ( ) : '' ;
2024-02-16 11:09:15 +00:00
return (
2024-02-20 08:01:06 +00:00
< div style = { fullscreen ? {
2024-02-22 02:03:15 +00:00
position : 'fixed' ,
2024-02-20 08:01:06 +00:00
top : 0 ,
left : 0 ,
width : '100%' ,
height : '100%' ,
backgroundColor : '#fff' ,
zIndex : 1000 ,
} : {
height : '100%' ,
2024-02-22 02:03:15 +00:00
position : 'relative' ,
2024-02-20 08:01:06 +00:00
} } >
2024-02-22 02:03:15 +00:00
< div
2024-02-22 09:36:03 +00:00
style = { { height : '100%' , position : 'absolute' , top : 0 , left : 0 , width : '100%' , background : "#00000033" , zIndex : 1000 , display : loading ? 'block' : 'none' } }
2024-02-22 02:03:15 +00:00
>
< Spin spinning = { true } style = { {
position : 'absolute' ,
top : '50%' ,
left : '50%' ,
marginTop : - 12 ,
marginLeft : - 12 ,
width : 24 ,
height : 24 ,
borderRadius : '50%' ,
} } size = 'large' / >
< / div >
2024-02-21 12:01:19 +00:00
< div >
< Button onClick = { ( ) = > {
setFullscreen ( ! fullscreen ) ;
} } >
{ fullscreen ? < FullscreenExitOutlined / > : < FullscreenOutlined / > }
{ fullscreen ? 'Exit Fullscreen' : 'Enter Fullscreen' }
< / Button >
2024-02-22 09:36:03 +00:00
{ totalRequests ? < > & nbsp ; & nbsp ; & nbsp ; < b > Request ID : < / b > { currentRequest ? . RequestID } < / > : "" }
2024-02-21 12:01:19 +00:00
< / div >
2024-02-16 11:09:15 +00:00
< Layout style = { {
2024-02-20 08:01:06 +00:00
overflow : 'auto' ,
2024-02-16 11:09:15 +00:00
width : '100%' ,
2024-02-20 08:01:06 +00:00
height : '100%' ,
2024-02-16 11:09:15 +00:00
maxWidth : '100%' ,
2024-02-21 11:11:02 +00:00
minHeight : '70%' ,
maxHeight : '70%' ,
2024-02-16 11:09:15 +00:00
display : 'flex' ,
padding : '8px' ,
} } >
2024-02-20 08:01:06 +00:00
< Content style = { {
textAlign : 'center' ,
color : '#fff' ,
backgroundColor : '#efefef' ,
height : '100%' ,
display : 'flex' ,
flexDirection : 'row' ,
} } >
2024-02-22 09:36:03 +00:00
{ totalRequests > 0 && < div
2024-02-20 08:01:06 +00:00
style = { {
width : "200px" ,
display : "flex" ,
flexDirection : "column" ,
flexGrow : 0 ,
} } >
< h2
style = { {
color : "#333" ,
padding : 10 ,
2024-02-21 11:11:02 +00:00
fontWeight : 'bold'
2024-02-20 08:01:06 +00:00
} }
2024-02-21 11:11:02 +00:00
> Files ( { currentRequest ? . Files ? . length } ) < / h2 >
{ currentRequest ? . Files . map ( ( file , index ) = > (
2024-02-20 08:01:06 +00:00
< FileCard key = { index } file = { file } isSelected = { index === selectedFileId } onClick = {
( ) = > {
2024-02-22 09:36:03 +00:00
setAndLoadSelectedFile ( currentRequest , index ) ;
2024-02-20 08:01:06 +00:00
}
2024-02-22 09:36:03 +00:00
} setIsReasonModalOpen = { setIsReasonModalOpen } / >
2024-02-20 08:01:06 +00:00
) ) }
2024-02-22 09:36:03 +00:00
< / div > }
2024-02-20 08:01:06 +00:00
< div style = { {
border : "1px solid #ccc" ,
2024-02-19 04:02:21 +00:00
flexGrow : 1 ,
2024-02-20 08:01:06 +00:00
height : '100%' ,
2024-02-19 04:02:21 +00:00
} } >
2024-03-06 04:43:11 +00:00
{ selectedFileData === "FAILED_TO_LOAD_FILE" ? < p style = { { color : "#333" } } > Failed to load file . < / p > : ( fileExtension === "pdf" ? ( < Viewer
fileUrl = { selectedFileData }
/ > ) : < d i v s t y l e = { {
2024-02-22 09:36:03 +00:00
height : "100%" ,
width : "100%" ,
overflow : "auto" ,
} } > < img width = { "100%" } src = { selectedFileData } alt = "file" / > < / div > ) }
2024-02-20 08:01:06 +00:00
< / div >
< / Content >
2024-02-21 11:11:02 +00:00
< Sider width = "400px" style = { siderStyle } >
2024-02-20 08:01:06 +00:00
< Space.Compact style = { { width : '100%' , marginBottom : 16 } } >
2024-02-21 11:11:02 +00:00
< Input value = {
2024-02-22 09:36:03 +00:00
` Sub: ${ filterSubsidiaries } , Date: ${ filterDateRange [ 0 ] ? ( filterDateRange [ 0 ] + " to " + filterDateRange [ 1 ] ) : "All" } , Reviewed: ${ filterReviewState } , Tests: ${ filterIncludeTests } `
2024-02-21 11:11:02 +00:00
} readOnly / >
2024-02-20 08:01:06 +00:00
< Button type = "primary" size = "large"
onClick = { ( ) = > {
setIsModalOpen ( true ) ;
} }
>
Filters
< / Button >
< / Space.Compact >
< div style = { { display : "flex" , justifyContent : "space-between" , marginBottom : 8 } } >
< div >
2024-02-22 02:03:15 +00:00
< Button type = "default" style = { { height : 38 } }
2024-02-21 11:11:02 +00:00
disabled = { currentRequestIndex === 1 }
onClick = { ( ) = > {
gotoPreviousRequest ( ) ;
} }
>
2024-02-20 08:01:06 +00:00
< ArrowLeftOutlined / >
2024-02-22 09:36:03 +00:00
Previou
2024-02-20 08:01:06 +00:00
< / Button >
2024-02-22 02:03:15 +00:00
< Button type = "default" style = { { height : 38 } }
2024-02-21 11:11:02 +00:00
disabled = { ! hasNextRequest }
onClick = { ( ) = > {
if ( ! hasNextRequest ) {
return ;
}
gotoNextRequest ( ) ;
} }
>
2024-02-20 08:01:06 +00:00
Next
< ArrowRightOutlined / >
< / Button >
2024-02-21 12:01:19 +00:00
< Input size = 'middle' addonBefore = "To" style = { { marginBottom : "4px" , marginLeft : "4px" , width : 180 } } defaultValue = { currentRequestIndex } addonAfter = {
2024-02-22 02:03:15 +00:00
< Button type = "default"
onClick = { ( ) = > {
2024-02-22 09:36:03 +00:00
if ( pageIndexToGoto > totalRequests ) {
2024-02-22 02:03:15 +00:00
message . error ( "RequestID is out of range." ) ;
return ;
}
if ( pageIndexToGoto < 1 ) {
message . error ( "RequestID is out of range." ) ;
return ;
}
setCurrentRequestIndex ( pageIndexToGoto ) ;
loadCurrentRequest ( pageIndexToGoto ) ;
} } >
2024-02-21 12:01:19 +00:00
Go to
< / Button >
2024-02-22 02:03:15 +00:00
}
value = { pageIndexToGoto }
onChange = { e = > {
setPageIndexToGoto ( parseInt ( e . target . value ) ) ;
} }
/ >
2024-02-16 11:09:15 +00:00
< / div >
2024-02-20 08:01:06 +00:00
< / div >
2024-02-22 09:36:03 +00:00
< h2 style = { { margin : "20px 0 10px 0" } } > { totalRequests ? ( "Request: " + currentRequestIndex + "/" + totalRequests ) : "No Request. Adjust your search criteria to see more results." } < / h2 >
{ totalRequests > 0 && < div >
< Input size = 'small' addonBefore = "Request ID" style = { { marginBottom : "4px" } } readOnly value = { currentRequest ? currentRequest . RequestID : "" } / >
< Input size = 'small' addonBefore = "Redemption" style = { { marginBottom : "4px" } } readOnly value = { currentRequest ? . RedemptionID ? currentRequest . RedemptionID : "" } / >
< Input size = 'small' addonBefore = "Uploaded date" style = { { marginBottom : "4px" } } readOnly value = { currentRequest ? currentRequest . created_at : "" } / >
< Input size = 'small' addonBefore = "Request time" style = { { marginBottom : "4px" } } readOnly value = { currentRequest ? currentRequest [ "Client Request Time (ms)" ] : "" } / >
< Input size = 'small' addonBefore = "Processing time" style = { { marginBottom : "4px" } } readOnly value = { currentRequest ? currentRequest [ "Server Processing Time (ms)" ] : "" } / >
< div style = { { marginBottom : "8px" , marginTop : "8px" , display : "flex" } } >
{ currentRequest && ( currentRequest [ "Is Reviewed" ] ? < Tag icon = { < CheckCircleOutlined / > } color = "success" style = { { padding : "4px 16px" } } >
Reviewed
< / Tag > : < Tag icon = { < ClockCircleFilled / > } color = "warning" style = { { padding : "4px 16px" } } >
Not Reviewed
< / Tag > ) }
< / div >
< / div > }
2024-02-20 08:01:06 +00:00
< / Sider >
< / Layout >
< Modal
title = { t ` Report Filters ` }
open = { isModalOpen }
width = { 700 }
onOk = {
( ) = > {
setIsModalOpen ( false ) ;
2024-02-21 11:11:02 +00:00
reloadFilters ( ) ;
2024-02-20 08:01:06 +00:00
}
}
onCancel = {
( ) = > {
setIsModalOpen ( false ) ;
}
}
>
< Form
style = { {
marginTop : 30 ,
} }
>
< Form.Item
name = 'dateRange'
label = { t ` Date (GMT+8) ` }
rules = { [
{
required : true ,
message : 'Please select a date range' ,
} ,
] }
style = { {
marginBottom : 10 ,
} }
>
< DatePicker.RangePicker
2024-02-22 09:36:03 +00:00
onChange = { ( date , dateString ) = > {
setFilterDateRange ( dateString ) ;
} }
2024-02-20 08:01:06 +00:00
style = { { width : 200 } }
/ >
< / Form.Item >
2024-02-21 11:11:02 +00:00
< Form.Item
name = 'subsidiary'
label = { t ` Subsidiary ` }
rules = { [
{
required : true ,
message : 'Please select a subsidiary' ,
} ,
] }
style = { {
marginBottom : 10 ,
} }
>
< Select
placeholder = 'Select a subsidiary'
style = { { width : 200 } }
options = { [
2024-02-23 05:46:32 +00:00
{ value : 'SEAO' , label : 'SEAO' } ,
2024-02-21 11:11:02 +00:00
{ value : 'SEAU' , label : 'SEAU' } ,
{ value : 'SESP' , label : 'SESP' } ,
{ value : 'SME' , label : 'SME' } ,
{ value : 'SEPCO' , label : 'SEPCO' } ,
{ value : 'TSE' , label : 'TSE' } ,
{ value : 'SEIN' , label : 'SEIN' } ,
] }
value = { filterSubsidiaries }
defaultValue = { filterSubsidiaries }
onChange = { setFilterSubsidiaries }
/ >
< / Form.Item >
< div style = { { marginTop : 10 , display : 'flex' , marginLeft : 0 , padding : 0 } } >
2024-02-20 08:01:06 +00:00
< Form.Item
2024-02-21 11:11:02 +00:00
name = 'reviewed'
label = { t ` Reviewed ` }
2024-02-20 08:01:06 +00:00
rules = { [
{
required : true ,
2024-02-21 11:11:02 +00:00
message : 'Please select review status' ,
2024-02-20 08:01:06 +00:00
} ,
] }
>
< Select
style = { { width : 200 } }
options = { [
2024-02-21 11:11:02 +00:00
{ label : 'All' , value : 'all' } ,
{ label : 'Reviewed' , value : 'reviewed' } ,
{ label : 'Not Reviewed' , value : 'not_reviewed' } ,
2024-02-20 08:01:06 +00:00
] }
2024-02-21 11:11:02 +00:00
value = { filterReviewState }
defaultValue = { filterReviewState }
onChange = { setFilterReviewState }
2024-02-20 08:01:06 +00:00
/ >
< / Form.Item >
< Form.Item
2024-02-21 11:11:02 +00:00
name = 'is_test'
label = { t ` Is Test ` }
2024-02-20 08:01:06 +00:00
rules = { [
{
required : true ,
2024-02-21 11:11:02 +00:00
message : 'Please select test status' ,
2024-02-20 08:01:06 +00:00
} ,
] }
style = { { marginLeft : 16 } }
>
< Select
style = { { width : 200 } }
options = { [
2024-02-21 11:11:02 +00:00
{ label : 'Include tests' , value : 'true' } ,
{ label : 'Exclude tests' , value : 'false' } ,
2024-02-20 08:01:06 +00:00
] }
2024-02-21 11:11:02 +00:00
value = { filterIncludeTests }
defaultValue = { filterIncludeTests }
onChange = { setFilterIncludesTests }
2024-02-20 08:01:06 +00:00
/ >
< / Form.Item >
< / div >
< / Form >
< / Modal >
2024-02-22 09:36:03 +00:00
< Modal
title = { t ` Review ` }
open = { isReasonModalOpen }
width = { 700 }
onOk = {
( ) = > {
}
}
onCancel = {
( ) = > {
setIsReasonModalOpen ( false ) ;
}
}
>
< Form
style = { {
marginTop : 30 ,
} }
>
< Form.Item
name = 'reason'
label = { t ` Reason for bad quality: ` }
style = { {
marginBottom : 10 ,
} }
>
< Select
placeholder = 'Select a reason'
style = { { width : 200 } }
options = { [
{ value : 'invalid_image' , label : t ` Invalid image ` } ,
{ value : 'missing_information' , label : t ` Missing information ` } ,
{ value : 'too_blurry_text' , label : t ` Too blurry text ` } ,
{ value : 'too_small_text' , label : t ` Too small text ` } ,
{ value : 'handwritten' , label : t ` Handwritten ` } ,
{ value : 'recheck' , label : t ` Recheck ` } ,
] }
/ >
< / Form.Item >
< / Form >
< / Modal >
{ totalRequests > 0 && < div
2024-02-20 08:01:06 +00:00
style = { {
2024-02-21 11:11:02 +00:00
height : '25%' ,
2024-02-20 08:01:06 +00:00
overflowY : 'auto' ,
} }
>
2024-02-22 02:03:15 +00:00
< StyledTable components = { components }
rowClassName = { ( ) = > 'editable-row' }
bordered dataSource = { dataSource } columns = { columns }
2024-02-20 08:01:06 +00:00
/ >
2024-02-22 09:36:03 +00:00
< / div > }
2024-02-20 08:01:06 +00:00
< / div >
2024-02-16 11:09:15 +00:00
) ;
} ;
2024-02-20 08:01:06 +00:00
export default ReviewPage ;