11"use client" ;
22
3- import React , { useState , useEffect } from "react" ;
3+ import React , { useState , useEffect , Suspense } from "react" ;
4+ import dynamic from 'next/dynamic' ;
45import Link from "next/link" ;
56import Image from "next/image" ;
67import { Card , CardContent , CardDescription , CardHeader , CardTitle } from "@/components/ui/card" ;
@@ -11,13 +12,18 @@ import { Switch } from "@/components/ui/switch";
1112import { Select , SelectContent , SelectItem , SelectTrigger , SelectValue } from "@/components/ui/select" ;
1213import { Skeleton } from "@/components/ui/skeleton" ;
1314import { useToast } from "@/hooks/use-toast" ;
14- import {
15- Dialog ,
16- DialogContent ,
17- DialogDescription ,
18- DialogHeader ,
19- DialogTitle ,
20- } from "@/components/ui/dialog" ;
15+
16+ // Dynamically import Dialog components with SSR disabled
17+ const JobSearchDialog = dynamic (
18+ ( ) => import ( '@/components/JobSearchDialog' ) . then ( ( mod ) => mod . JobSearchDialog ) ,
19+ { ssr : false }
20+ ) ;
21+
22+ const SuccessDialog = dynamic (
23+ ( ) => import ( '@/components/SuccessDialog' ) . then ( ( mod ) => mod . SuccessDialog ) ,
24+ { ssr : false }
25+ ) ;
26+
2127import {
2228 buildLinkedInJobURL ,
2329 validateFilters ,
@@ -43,6 +49,10 @@ import {
4349import { useTheme } from "next-themes" ;
4450
4551export default function LandingPage ( ) {
52+ const { toast } = useToast ( ) ;
53+ const { theme, setTheme } = useTheme ( ) ;
54+ const [ copied , setCopied ] = useState ( false ) ;
55+ // Use the imported JobFilters type from linkedin-url-builder
4656 const [ filters , setFilters ] = useState < JobFilters > ( {
4757 keywords : "" ,
4858 location : "" ,
@@ -55,18 +65,13 @@ export default function LandingPage() {
5565
5666 const [ generatedUrl , setGeneratedUrl ] = useState ( "" ) ;
5767 const [ error , setError ] = useState ( "" ) ;
58- const [ copied , setCopied ] = useState ( false ) ;
59- const [ isLoading , setIsLoading ] = useState ( true ) ;
6068 const [ showModal , setShowModal ] = useState ( false ) ;
61-
62- const { toast } = useToast ( ) ;
63- const { theme, setTheme } = useTheme ( ) ;
64-
65- useEffect ( ( ) => {
66- setTimeout ( ( ) => setIsLoading ( false ) , 1000 ) ;
67- } , [ ] ) ;
69+ const [ isLoading , setIsLoading ] = useState ( true ) ;
6870
6971 useEffect ( ( ) => {
72+ // Set loading to false when component mounts
73+ setIsLoading ( false ) ;
74+
7075 const handleBeforeUnload = ( e : BeforeUnloadEvent ) => {
7176 if ( showModal && generatedUrl ) {
7277 e . preventDefault ( ) ;
@@ -75,7 +80,9 @@ export default function LandingPage() {
7580 } ;
7681
7782 window . addEventListener ( "beforeunload" , handleBeforeUnload ) ;
78- return ( ) => window . removeEventListener ( "beforeunload" , handleBeforeUnload ) ;
83+ return ( ) => {
84+ window . removeEventListener ( "beforeunload" , handleBeforeUnload ) ;
85+ } ;
7986 } , [ showModal , generatedUrl ] ) ;
8087
8188 const handleGenerate = ( ) => {
@@ -238,7 +245,7 @@ export default function LandingPage() {
238245 </ Label >
239246 < Input
240247 id = "keywords"
241- placeholder = "e.g. Python Developer "
248+ placeholder = "e.g. Software Engineer "
242249 value = { filters . keywords }
243250 onChange = { ( e ) => updateFilter ( "keywords" , e . target . value ) }
244251 className = { error ? "border-destructive" : "" }
@@ -250,7 +257,7 @@ export default function LandingPage() {
250257 < Label htmlFor = "location" > Location</ Label >
251258 < Input
252259 id = "location"
253- placeholder = "e.g. Karachi, Pakistan "
260+ placeholder = "e.g. San Francisco, California "
254261 value = { filters . location }
255262 onChange = { ( e ) => updateFilter ( "location" , e . target . value ) }
256263 />
@@ -427,64 +434,18 @@ export default function LandingPage() {
427434 </ div >
428435 </ footer >
429436
430- < Dialog open = { showModal } onOpenChange = { setShowModal } >
431- < DialogContent className = "sm:max-w-lg" >
432- < DialogHeader >
433- < div className = "flex items-center gap-2 mb-2" >
434- < div className = "flex h-10 w-10 items-center justify-center rounded-full bg-green-100 dark:bg-green-900" >
435- < Check className = "h-5 w-5 text-green-600 dark:text-green-400" />
436- </ div >
437- < DialogTitle className = "text-xl" > Link generated successfully!</ DialogTitle >
438- </ div >
439- < DialogDescription className = "text-base" >
440- { filters . keywords && filters . location
441- ? `${ filters . keywords } in ${ filters . location } `
442- : filters . keywords
443- ? filters . keywords
444- : "Your job search" }
445- </ DialogDescription >
446- </ DialogHeader >
447-
448- < div className = "space-y-4 mt-2" >
449- < div className = "space-y-2" >
450- < Label className = "text-sm text-muted-foreground" > Your LinkedIn Job Search URL</ Label >
451- < div className = "flex gap-2" >
452- < Input value = { generatedUrl } readOnly className = "font-mono text-xs" />
453- < Button variant = "outline" size = "icon" onClick = { handleCopy } >
454- { copied ? (
455- < Check className = "h-4 w-4 text-green-600" />
456- ) : (
457- < Copy className = "h-4 w-4" />
458- ) }
459- </ Button >
460- </ div >
461- </ div >
462-
463- < div className = "rounded-lg border border-green-200 dark:border-green-900 bg-green-50 dark:bg-green-950 p-3" >
464- < p className = "text-xs text-green-700 dark:text-green-300" >
465- { getFilterSummary ( filters ) }
466- </ p >
467- </ div >
468-
469- < div className = "flex gap-2 pt-2" >
470- < Button
471- variant = "default"
472- className = "flex-1 bg-green-600 hover:bg-green-700 dark:bg-green-600 dark:hover:bg-green-700"
473- onClick = { ( ) => {
474- window . open ( generatedUrl , "_blank" , "noopener,noreferrer" ) ;
475- setShowModal ( false ) ;
476- } }
477- >
478- < ExternalLink className = "h-4 w-4 mr-2" />
479- Open in LinkedIn
480- </ Button >
481- < Button variant = "outline" onClick = { ( ) => setShowModal ( false ) } >
482- Close
483- </ Button >
484- </ div >
485- </ div >
486- </ DialogContent >
487- </ Dialog >
437+ < Suspense fallback = { null } >
438+ < SuccessDialog
439+ open = { showModal }
440+ onOpenChange = { setShowModal }
441+ generatedUrl = { generatedUrl }
442+ filters = { {
443+ ...filters ,
444+ location : filters . location || ''
445+ } }
446+ getFilterSummary = { getFilterSummary }
447+ />
448+ </ Suspense >
488449 </ div >
489450 ) ;
490451}
0 commit comments