1+ // app/home/in-house/_components/table/InHouseTable.tsx
12"use client" ;
23
34import { useCallback , useEffect , useMemo , useState } from "react" ;
@@ -85,9 +86,6 @@ const capitalize = (str: string) =>
8586
8687/**
8788 * Converts display position to uppercase format
88- * Input → Output Examples:
89- * "frontend developer" → "FRONTEND DEVELOPER"
90- * "ui/ux designer" → "UI/UX DESIGNER"
9189 * @param position - Display position string
9290 * @returns Uppercase position or dash for empty values
9391 */
@@ -97,8 +95,8 @@ const formatDisplayPosition = (position: string | null | undefined): string => {
9795} ;
9896
9997/**
100- * NDA Email Button Component
101- * Handles sending NDA signing requests to team members
98+ * Enhanced NDA Email Button Component
99+ * Now integrates with the new storage-first NDA process
102100 */
103101const SendNdaButton = ( { codev, onSendNdaEmail } : NdaEmailDialogProps ) => {
104102 const [ isSending , setIsSending ] = useState ( false ) ;
@@ -135,8 +133,8 @@ const SendNdaButton = ({ codev, onSendNdaEmail }: NdaEmailDialogProps) => {
135133} ;
136134
137135/**
138- * Main InHouseTable Component
139- * Displays team member data with responsive design and inline editing
136+ * Main InHouseTable Component with Enhanced NDA Storage Integration
137+ * Now properly handles NDA signature and document URLs from Supabase Storage
140138 */
141139export function InHouseTable ( {
142140 data,
@@ -188,8 +186,8 @@ export function InHouseTable({
188186 } ;
189187
190188 /**
191- * Sends NDA signing request email to team member
192- * Creates unique token and database record for tracking
189+ * Enhanced NDA email sending with proper database tracking
190+ * Now creates NDA request records and generates secure tokens
193191 */
194192 const handleSendNdaEmail = async (
195193 codevId : string ,
@@ -250,33 +248,98 @@ export function InHouseTable({
250248 } ;
251249
252250 /**
253- * Downloads NDA document for signed members
251+ * Enhanced NDA document download function
252+ * Now downloads from Supabase Storage URLs instead of base64 data
254253 * @param codevId - ID of the member whose NDA to download
255254 */
256255 const handleDownloadNda = async ( codevId : string ) => {
257256 try {
258257 const { data, error } = await supabase
259258 . from ( "codev" )
260- . select ( "nda_document, first_name, last_name" )
259+ . select ( "nda_document, nda_signature, first_name, last_name" )
261260 . eq ( "id" , codevId )
262261 . single ( ) ;
263262
264- if ( error || ! data || ! data . nda_document ) {
265- throw new Error ( "Failed to fetch NDA document " ) ;
263+ if ( error || ! data ) {
264+ throw new Error ( "Failed to fetch member data " ) ;
266265 }
267266
267+ // Check if NDA document URL exists
268+ if ( ! data . nda_document ) {
269+ throw new Error ( "No signed NDA document found for this member" ) ;
270+ }
271+
272+ // Download the document directly from the storage URL
273+ const response = await fetch ( data . nda_document ) ;
274+ if ( ! response . ok ) {
275+ throw new Error ( "Failed to download NDA document" ) ;
276+ }
277+
278+ const blob = await response . blob ( ) ;
279+
268280 // Create download link and trigger download
281+ const url = window . URL . createObjectURL ( blob ) ;
269282 const link = document . createElement ( "a" ) ;
270- link . href = data . nda_document ;
283+ link . href = url ;
271284 link . download = `NDA_${ data . first_name } _${ data . last_name } .pdf` ;
272285 document . body . appendChild ( link ) ;
273286 link . click ( ) ;
287+
288+ // Cleanup
274289 document . body . removeChild ( link ) ;
290+ window . URL . revokeObjectURL ( url ) ;
275291
276292 toast . success ( "NDA document downloaded successfully" ) ;
277293 } catch ( error ) {
278294 console . error ( "Error downloading NDA:" , error ) ;
279- toast . error ( "Failed to download NDA document" ) ;
295+ toast . error (
296+ error instanceof Error
297+ ? error . message
298+ : "Failed to download NDA document"
299+ ) ;
300+ }
301+ } ;
302+
303+ /**
304+ * Downloads NDA signature image separately
305+ * @param codevId - ID of the member whose signature to download
306+ */
307+ const handleDownloadSignature = async ( codevId : string ) => {
308+ try {
309+ const { data, error } = await supabase
310+ . from ( "codev" )
311+ . select ( "nda_signature, first_name, last_name" )
312+ . eq ( "id" , codevId )
313+ . single ( ) ;
314+
315+ if ( error || ! data || ! data . nda_signature ) {
316+ throw new Error ( "No signature found for this member" ) ;
317+ }
318+
319+ // Download the signature directly from the storage URL
320+ const response = await fetch ( data . nda_signature ) ;
321+ if ( ! response . ok ) {
322+ throw new Error ( "Failed to download signature" ) ;
323+ }
324+
325+ const blob = await response . blob ( ) ;
326+
327+ // Create download link and trigger download
328+ const url = window . URL . createObjectURL ( blob ) ;
329+ const link = document . createElement ( "a" ) ;
330+ link . href = url ;
331+ link . download = `Signature_${ data . first_name } _${ data . last_name } .png` ;
332+ document . body . appendChild ( link ) ;
333+ link . click ( ) ;
334+
335+ // Cleanup
336+ document . body . removeChild ( link ) ;
337+ window . URL . revokeObjectURL ( url ) ;
338+
339+ toast . success ( "Signature downloaded successfully" ) ;
340+ } catch ( error ) {
341+ console . error ( "Error downloading signature:" , error ) ;
342+ toast . error ( "Failed to download signature" ) ;
280343 }
281344 } ;
282345
@@ -291,7 +354,6 @@ export function InHouseTable({
291354
292355 /**
293356 * Advanced pagination handler for direct page navigation
294- * Implements step-by-step navigation since direct page setting isn't available
295357 */
296358 const setCurrentPage = useCallback ( ( pageOrFunction : number | ( ( page : number ) => number ) ) => {
297359 const page =
@@ -464,7 +526,7 @@ export function InHouseTable({
464526 </ DropdownMenuPortal >
465527 </ DropdownMenuSub >
466528
467- { /* NDA Status submenu with action buttons */ }
529+ { /* Enhanced NDA Status submenu with storage-based actions */ }
468530 < DropdownMenuSub >
469531 < DropdownMenuSubTrigger >
470532 NDA Status
@@ -476,17 +538,28 @@ export function InHouseTable({
476538 { item . nda_status ? "Yes" : "No" }
477539 </ span >
478540
479- { /* Conditional NDA action buttons */ }
541+ { /* Enhanced NDA action buttons */ }
480542 { item . nda_status ? (
481- < Button
482- variant = "outline"
483- size = "sm"
484- className = "ml-2 text-green-500 hover:text-green-600 dark:text-green-200 dark:hover:text-green-300"
485- onClick = { ( ) => handleDownloadNda ( item . id ) }
486- >
487- < Download className = "mr-1 h-4 w-4" />
488- Download
489- </ Button >
543+ < div className = "flex gap-1" >
544+ < Button
545+ variant = "outline"
546+ size = "sm"
547+ className = "text-green-500 hover:text-green-600 dark:text-green-200 dark:hover:text-green-300"
548+ onClick = { ( ) => handleDownloadNda ( item . id ) }
549+ >
550+ < Download className = "mr-1 h-3 w-3" />
551+ PDF
552+ </ Button >
553+ < Button
554+ variant = "outline"
555+ size = "sm"
556+ className = "text-blue-500 hover:text-blue-600 dark:text-blue-200 dark:hover:text-blue-300"
557+ onClick = { ( ) => handleDownloadSignature ( item . id ) }
558+ >
559+ < Download className = "mr-1 h-3 w-3" />
560+ Sig
561+ </ Button >
562+ </ div >
490563 ) : item . nda_request_sent ? (
491564 < Button
492565 variant = "outline"
@@ -606,24 +679,37 @@ export function InHouseTable({
606679 ) }
607680 </ TableCell >
608681
609- { /* NDA Status column with action buttons */ }
682+ { /* Enhanced NDA Status column with storage-based action buttons */ }
610683 < TableCell className = "dark:text-light-900 hidden px-2 py-2 text-base text-black 2xl:table-cell" >
611684 < div className = "flex items-center gap-2" >
612685 < span className = { `${ getNdaStatusColor ( item . nda_status ) } ` } >
613686 { item . nda_status ? "Yes" : "No" }
614687 </ span >
615688
616- { /* Conditional NDA action buttons */ }
689+ { /* Enhanced NDA action buttons with dual download options */ }
617690 { item . nda_status ? (
618- < Button
619- variant = "outline"
620- size = "sm"
621- className = "ml-2 text-green-500 hover:text-green-600 dark:text-green-200 dark:hover:text-green-300"
622- onClick = { ( ) => handleDownloadNda ( item . id ) }
623- >
624- < Download className = "mr-1 h-4 w-4" />
625- Download
626- </ Button >
691+ < div className = "flex gap-1" >
692+ < Button
693+ variant = "outline"
694+ size = "sm"
695+ className = "text-green-500 hover:text-green-600 dark:text-green-200 dark:hover:text-green-300"
696+ onClick = { ( ) => handleDownloadNda ( item . id ) }
697+ title = "Download NDA Document"
698+ >
699+ < Download className = "mr-1 h-4 w-4" />
700+ PDF
701+ </ Button >
702+ < Button
703+ variant = "outline"
704+ size = "sm"
705+ className = "text-blue-500 hover:text-blue-600 dark:text-blue-200 dark:hover:text-blue-300"
706+ onClick = { ( ) => handleDownloadSignature ( item . id ) }
707+ title = "Download Signature"
708+ >
709+ < Download className = "mr-1 h-4 w-4" />
710+ Signature
711+ </ Button >
712+ </ div >
627713 ) : item . nda_request_sent ? (
628714 < Button
629715 variant = "outline"
@@ -691,9 +777,9 @@ export function InHouseTable({
691777 </ Table >
692778 </ div >
693779
694- { /* Pagination Controls - Show when there are multiple pages */ }
780+ { /* Pagination Controls - Only show when data exceeds page size */ }
695781 < div className = "relative w-full" >
696- { pagination . totalPages > 1 && (
782+ { data . length > pageSize . applicants && (
697783 < DefaultPagination
698784 currentPage = { pagination . currentPage }
699785 handleNextPage = { handleNextPage }
0 commit comments