@@ -4,11 +4,20 @@ import React from "react";
4
4
import "@/public/vendor/handsontable/handsontable.full.min.css" ;
5
5
import { Brand , DataroomBrand } from "@prisma/client" ;
6
6
7
+ import { Button } from "@/components/ui/button" ;
8
+
9
+ import { cn } from "@/lib/utils" ;
10
+
7
11
import { TDocumentData } from "../dataroom/dataroom-view" ;
8
12
import Nav from "../nav" ;
9
13
10
14
// Define the type for the JSON data
11
- type SheetData = { [ key : string ] : any } ;
15
+ type RowData = { [ key : string ] : any } ;
16
+ type SheetData = {
17
+ sheetName : string ;
18
+ columnData : string [ ] ;
19
+ rowData : RowData [ ] ;
20
+ } ;
12
21
13
22
const trackPageView = async ( data : {
14
23
linkId : string ;
@@ -34,8 +43,7 @@ export default function ExcelViewer({
34
43
documentId,
35
44
documentName,
36
45
versionNumber,
37
- columns,
38
- data,
46
+ sheetData,
39
47
brand,
40
48
dataroomId,
41
49
setDocumentData,
@@ -45,15 +53,15 @@ export default function ExcelViewer({
45
53
documentId : string ;
46
54
documentName : string ;
47
55
versionNumber : number ;
48
- columns : string [ ] ;
49
- data : SheetData [ ] ;
56
+ sheetData : SheetData [ ] ;
50
57
brand ?: Partial < Brand > | Partial < DataroomBrand > | null ;
51
58
dataroomId ?: string ;
52
59
setDocumentData ?: React . Dispatch < React . SetStateAction < TDocumentData | null > > ;
53
60
} ) {
54
61
const [ availableWidth , setAvailableWidth ] = useState < number > ( 200 ) ;
55
62
const [ availableHeight , setAvailableHeight ] = useState < number > ( 200 ) ;
56
63
const [ handsontableLoaded , setHandsontableLoaded ] = useState < boolean > ( false ) ;
64
+ const [ selectedSheetIndex , setSelectedSheetIndex ] = useState < number > ( 0 ) ;
57
65
58
66
useEffect ( ( ) => {
59
67
const script = document . createElement ( "script" ) ;
@@ -84,8 +92,8 @@ export default function ExcelViewer({
84
92
const calculateSize = ( ) => {
85
93
if ( containerRef . current ) {
86
94
const offset = containerRef . current . getBoundingClientRect ( ) ;
87
- setAvailableWidth ( Math . max ( offset . width - 60 , 200 ) ) ;
88
- setAvailableHeight ( Math . max ( offset . height - 10 , 200 ) ) ;
95
+ setAvailableWidth ( Math . max ( offset . width , 200 ) ) ;
96
+ setAvailableHeight ( Math . max ( offset . height - 50 , 200 ) ) ;
89
97
}
90
98
} ;
91
99
@@ -113,7 +121,7 @@ export default function ExcelViewer({
113
121
documentId,
114
122
viewId,
115
123
duration,
116
- pageNumber : 1 ,
124
+ pageNumber : selectedSheetIndex + 1 ,
117
125
versionNumber,
118
126
dataroomId,
119
127
} ) ;
@@ -130,24 +138,27 @@ export default function ExcelViewer({
130
138
documentId,
131
139
viewId,
132
140
duration,
133
- pageNumber : 1 ,
141
+ pageNumber : selectedSheetIndex + 1 ,
134
142
versionNumber,
135
143
dataroomId,
136
144
} ) ; // Also capture duration if component unmounts while visible
145
+ startTimeRef . current = Date . now ( ) ;
137
146
}
138
147
document . removeEventListener ( "visibilitychange" , handleVisibilityChange ) ;
139
148
} ;
140
- } , [ ] ) ;
149
+ } , [ selectedSheetIndex ] ) ;
141
150
142
151
useEffect ( ( ) => {
143
152
const handleBeforeUnload = ( ) => {
153
+ if ( ! visibilityRef . current ) return ;
154
+
144
155
const duration = Date . now ( ) - startTimeRef . current ;
145
156
trackPageView ( {
146
157
linkId,
147
158
documentId,
148
159
viewId,
149
160
duration,
150
- pageNumber : 1 ,
161
+ pageNumber : selectedSheetIndex + 1 ,
151
162
versionNumber,
152
163
dataroomId,
153
164
} ) ;
@@ -158,22 +169,24 @@ export default function ExcelViewer({
158
169
return ( ) => {
159
170
window . removeEventListener ( "beforeunload" , handleBeforeUnload ) ;
160
171
} ;
161
- } , [ ] ) ;
172
+ } , [ selectedSheetIndex ] ) ;
162
173
163
174
useEffect ( ( ) => {
164
- if ( handsontableLoaded && data . length && columns . length ) {
175
+ if ( handsontableLoaded && sheetData . length ) {
165
176
if ( hotInstanceRef . current ) {
166
177
hotInstanceRef . current . destroy ( ) ;
167
178
}
168
179
180
+ const { columnData, rowData } = sheetData [ selectedSheetIndex ] ;
181
+
169
182
// @ts -ignore - Handsontable import has not types
170
183
hotInstanceRef . current = new Handsontable ( hotRef . current ! , {
171
- data : data ,
184
+ data : rowData ,
172
185
readOnly : true ,
173
186
disableVisualSelection : true ,
174
187
comments : false ,
175
188
contextMenu : false ,
176
- colHeaders : columns ,
189
+ colHeaders : columnData ,
177
190
rowHeaders : true ,
178
191
manualColumnResize : true ,
179
192
width : availableWidth ,
@@ -190,7 +203,13 @@ export default function ExcelViewer({
190
203
// },
191
204
} ) ;
192
205
}
193
- } , [ handsontableLoaded , data , columns , availableHeight , availableWidth ] ) ;
206
+ } , [
207
+ handsontableLoaded ,
208
+ sheetData ,
209
+ selectedSheetIndex ,
210
+ availableHeight ,
211
+ availableWidth ,
212
+ ] ) ;
194
213
195
214
return (
196
215
< >
@@ -202,11 +221,27 @@ export default function ExcelViewer({
202
221
type = "sheet"
203
222
/>
204
223
< div
205
- style = { { height : "calc(100vh - 64px)" } }
206
- className = "flex h-screen items-center justify-center "
224
+ style = { { height : "calc(100dvh - 64px)" } }
225
+ className = "mx-2 flex h-screen flex-col sm:mx-6 lg:mx-8 "
207
226
ref = { containerRef }
208
227
>
209
- < div ref = { hotRef } > </ div >
228
+ < div className = "" ref = { hotRef } > </ div >
229
+ < div className = "flex max-w-fit divide-x divide-gray-200 overflow-x-scroll whitespace-nowrap rounded-b-sm bg-[#f0f0f0] px-1 " >
230
+ { sheetData . map ( ( sheet , index ) => (
231
+ < div className = "px-1" key = { sheet . sheetName } >
232
+ < Button
233
+ onClick = { ( ) => setSelectedSheetIndex ( index ) }
234
+ className = { cn (
235
+ "mb-1 rounded-none rounded-b-sm bg-[#f0f0f0] font-normal text-gray-950 hover:bg-gray-50" ,
236
+ index === selectedSheetIndex &&
237
+ "bg-white font-medium text-black ring-1 ring-gray-500 hover:bg-white" ,
238
+ ) }
239
+ >
240
+ { sheet . sheetName }
241
+ </ Button >
242
+ </ div >
243
+ ) ) }
244
+ </ div >
210
245
</ div >
211
246
</ >
212
247
) ;
0 commit comments