22
33import React , { useState , useEffect } from "react" ;
44import Link from "next/link" ;
5- import { Menu , X , Slack } from "lucide-react" ;
5+ import { Menu , X , Slack , Plus } from "lucide-react" ;
66import Logo from "./Logo" ;
77import ThemeToggle from "./ThemeToggle" ;
88import GitHubStarButton from "./GitHubStarsButton" ;
9+ import { getCalApi } from "@calcom/embed-react" ;
10+ import Image from "next/image" ;
911
10- // constants/contact.ts
11- export const CONTACT_EMAIL = '[email protected] ' ; 12- export const CONTACT_MAILTO = `mailto:${ CONTACT_EMAIL } ` ;
1312
1413interface NavigationItem {
1514 name : string ;
@@ -21,7 +20,19 @@ const Navbar: React.FC = () => {
2120 const [ isMenuOpen , setIsMenuOpen ] = useState ( false ) ;
2221 const [ activeSection , setActiveSection ] = useState < string > ( "" ) ;
2322 const [ scrolled , setScrolled ] = useState ( false ) ;
24-
23+ const rawCalLink = process . env . NEXT_PUBLIC_CAL_DATA_LINK ?? "" ;
24+ const calLink = rawCalLink . trim ( ) ;
25+ const isCalReady = calLink . length > 0 ;
26+ if ( ! isCalReady ) {
27+ console . error ( "NEXT_PUBLIC_CAL_DATA_LINK environment variable is not set" )
28+ }
29+ const CAL_CONFIG = {
30+ theme : "light" ,
31+ hideEventTypeDetails : true ,
32+ layout : "month_view"
33+ } as const ;
34+
35+ const CAL_CONFIG_STRING = JSON . stringify ( CAL_CONFIG ) ;
2536 const navigation : NavigationItem [ ] = [
2637 { name : "Features" , href : "/#features" } ,
2738 { name : "Integrations" , href : "/#integrations" } ,
@@ -39,12 +50,45 @@ const Navbar: React.FC = () => {
3950 href : "https://join.slack.com/t/opsimate/shared_invite/zt-39bq3x6et-NrVCZzH7xuBGIXmOjJM7gA" ,
4051 external : true ,
4152 } ;
53+ useEffect ( ( ) => {
54+ if ( ! isCalReady ) {
55+ return ;
56+ }
57+ ( async function ( ) {
58+ try {
59+ const cal = await getCalApi ( { "namespace" : "30min" } ) ;
60+ cal ( "ui" , { "hideEventTypeDetails" : true , "layout" : "month_view" } ) ;
61+ } catch ( error ) {
62+ console . error ( "Failed to initialize Cal.com:" , error ) ;
63+ }
64+ } ) ( ) ;
65+ } , [ isCalReady ] )
4266
43- const contactLink : NavigationItem = {
44- name : "Contact Us" ,
45- href : CONTACT_MAILTO ,
46- external : true ,
47- } ;
67+ // Highlight active section on scroll
68+ useEffect ( ( ) => {
69+ const sections = document . querySelectorAll ( "section[id]" ) ;
70+ const observer = new IntersectionObserver (
71+ ( entries ) => {
72+ entries . forEach ( ( entry ) => {
73+ if ( entry . isIntersecting ) {
74+ setActiveSection ( entry . target . id ) ;
75+ }
76+ } ) ;
77+ } ,
78+ { rootMargin : "-50% 0px -50% 0px" }
79+ ) ;
80+
81+ sections . forEach ( ( section ) => observer . observe ( section ) ) ;
82+ return ( ) => sections . forEach ( ( section ) => observer . unobserve ( section ) ) ;
83+ } , [ ] ) ;
84+
85+ // Blur effect on scroll
86+ useEffect ( ( ) => {
87+ const handleScroll = ( ) => setScrolled ( window . scrollY > 20 ) ;
88+ handleScroll ( ) ;
89+ window . addEventListener ( "scroll" , handleScroll ) ;
90+ return ( ) => window . removeEventListener ( "scroll" , handleScroll ) ;
91+ } , [ ] ) ;
4892
4993 // Highlight active section on scroll
5094 useEffect ( ( ) => {
@@ -121,29 +165,37 @@ const Navbar: React.FC = () => {
121165 < Slack size = { 18 } aria-hidden = "true" />
122166 { slackLink . name }
123167 </ Link >
124-
125168 { /* Contact Us button */ }
126- < a
127- href = { contactLink . href }
128- className = "px-4 py-2 bg-primary-600 text-white rounded-lg hover:bg-primary-700 transition-colors duration-200"
129- >
130- { contactLink . name }
131- </ a >
132-
169+ {
170+ isCalReady && (
171+ < button className = "px-4 py-2 bg-primary-600 text-white rounded-lg hover:bg-primary-700
172+ duration-200
173+ flex items-center gap-2 flex-shrink-0
174+ transition-all group"
175+ data-cal-namespace = "30min" data-cal-link = { calLink } data-cal-config = { CAL_CONFIG_STRING } >
176+ < div className = "flex items-center gap-2 group-hover:gap-8 transition-all duration-300 relative" >
177+ < Image src = { '/images/logo.png' } width = { 28 } height = { 28 } alt = "logo" className = "rounded-full bg-white flex-shrink-0" > </ Image >
178+ < div className = "flex items-center gap-0 absolute left-[28px] transform -translate-x-full opacity-0 group-hover:translate-x-0 group-hover:opacity-100 transition-all duration-300" >
179+ < div className = "w-5 h-5 rounded-full flex items-center justify-center text-[10px] ml-1 mr-1" > < Plus width = { 20 } height = { 20 } > </ Plus > </ div >
180+ < div className = "w-7 h-7 rounded-full dark:bg-white/10 bg-white/20 flex items-center justify-center text-[10px] ml-1 mr-1" > You</ div >
181+ </ div >
182+ < span className = "whitespace-nowrap relative block text-base font-bold ml-0 group-hover:ml-10 transition-all duration-300" > Book a Call</ span >
183+ </ div >
184+ </ button >
185+ )
186+ }
133187 < ThemeToggle />
134188 </ div >
135-
136189 { /* Mobile menu button */ }
137190 < div className = "md:hidden" >
138- < button
191+ < button
139192 onClick = { ( ) => setIsMenuOpen ( ! isMenuOpen ) }
140193 className = "text-surface-700 dark:text-surface-300 hover:text-primary-500 dark:hover:text-primary-400 transition-colors duration-200"
141194 >
142195 { isMenuOpen ? < X size = { 24 } /> : < Menu size = { 24 } /> }
143196 </ button >
144197 </ div >
145198 </ div >
146-
147199 { /* Mobile Navigation */ }
148200 { isMenuOpen && (
149201 < div className = "md:hidden py-4 border-t border-surface-200 dark:border-surface-800" >
@@ -168,13 +220,13 @@ const Navbar: React.FC = () => {
168220 ) ) }
169221
170222 { /* Mobile Contact Us link */ }
171- < a
172- href = { contactLink . href }
173- className = "text-surface-700 dark:text-surface-300 hover:text- primary-500 dark: hover:text -primary-400 font-medium transition-colors duration-200 px-2 py-1"
174- onClick = { ( ) => setIsMenuOpen ( false ) }
175- >
176- { contactLink . name }
177- </ a >
223+ {
224+ isCalReady && (
225+ < button className = "font-medium transition-colors duration-200 px-2 py-2 md:w-[20%] w-[35%] bg- primary-600 text-white rounded-lg hover:bg -primary-700 cursor-pointer" data-cal-namespace = "30min" data-cal-link = { calLink } data-cal-config = { CAL_CONFIG_STRING } >
226+ Book A Call
227+ </ button >
228+ )
229+ }
178230 </ div >
179231 </ div >
180232 ) }
0 commit comments