Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 39 additions & 5 deletions app/dashboard/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,17 @@ import { ProfileData } from "@/components/profile-data";
import Readme from "@/components/readme";
import Resume from "@/components/Resume and CV/resume";
import { StudentDashboard } from "@/components/student-dashboard";
import dynamic from "next/dynamic";

export default function Page() {
const [data, setData] = useState<unknown[]>([]);
const [loading, setLoading] = useState(true);
const [isResumeBuildingMode, setIsResumeBuildingMode] = useState(false);

const JoyrideTour = dynamic(
() => import("@/app/onboarding/product-tour/joyride"),
{ ssr: false }
);

useEffect(() => {
getCertificateData().then((fetchedData) => {
Expand Down Expand Up @@ -58,19 +64,24 @@ export default function Page() {
</div>

{/* Scrollable content */}
<div className="flex-1 overflow-y-auto px-4 lg:px-6 landing-page">
<div className="flex-1 overflow-y-auto px-4 lg:px-6 landing-page" id="dashboard-content">
<div className="@container/main flex flex-1 flex-row gap-6 py-4">
<div className={`${isResumeBuildingMode ? 'flex-1' : 'flex-[3]'} flex flex-col gap-4`}>
<Tabs defaultValue="stats">
<TabsList>
<TabsList id="tabs-section">
<TabsTrigger value="stats">Stats</TabsTrigger>
<TabsTrigger value="portfolio">Portfolio</TabsTrigger>
<TabsTrigger value="readme">Readme</TabsTrigger>
<TabsTrigger value="resume">Resume & CV</TabsTrigger>
<TabsTrigger disabled value="achievements">Achievements</TabsTrigger>
<TabsTrigger value="resume">Resume</TabsTrigger>
<TabsTrigger value="cv">CV</TabsTrigger>
<TabsTrigger disabled value="achievments">
Achievements
</TabsTrigger>
</TabsList>

<TabsContent value="stats" className="space-y-4">
<TabsContent value="stats" className="space-y-4" id="stats-graph">
<SectionCards />
<ChartAreaInteractive />
{loading ? (
Expand All @@ -84,6 +95,7 @@ export default function Page() {
<DataTable data={data as { header: string; type: string; id: number; status: string; target: string; limit: string; reviewer: string; }[]} />
)}
</TabsContent>

<TabsContent value="portfolio">
<StudentDashboard />
</TabsContent>
Expand All @@ -98,9 +110,31 @@ export default function Page() {
<ProfileData />
</div>
)}
<Tabs defaultValue="tabs-section">
<TabsContent value="readme">
<Readme />
</TabsContent>

<TabsContent value="resume">
Make changes to your account here.
</TabsContent>

<TabsContent value="cv">
Change your password here.
</TabsContent>

<TabsContent value="achievments">
Make changes to your account here.
</TabsContent>
</Tabs>
</div>

<div className="flex-[1] flex flex-col" id="profile-section">
<ProfileData />
</div>
</div>
</div>
</SidebarInset>
{<JoyrideTour onFinish={() => console.log("✅ Joyride complete!")} />}
</SidebarProvider>
);
}
}
64 changes: 64 additions & 0 deletions app/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,70 @@
border: initial;
}

{/* Make the spotlight transparent but with a glowing outline
.react-joyride__spotlight {
background-color: transparent !important;
border-radius: 12px !important;
box-shadow: 0 0 5px 4px rgba(255, 255, 255, 0.775) !important;
transition: box-shadow 0.3s ease-in-out;
}*/}

/* 💅 Custom Joyride Tooltip Styling */
.react-joyride__tooltip {
background-color: #1a1a1a !important; /* dark theme */
color: #f0f0f0 !important; /* lignpht text */
border-radius: 12px !important;
border: 1px solid #333 !important;
box-shadow: 0 4px 24px rgba(0, 0, 0, 0.6) !important;
font-family: 'Inter', sans-serif !important;
padding: 1rem 1.25rem !important;
max-width: 340px !important;
}

.react-joyride__tooltip h4 {
font-size: 1.125rem !important;
font-weight: 600 !important;
color: #43755d !important; /* Dijkstra accent green */
margin-bottom: 0.5rem !important;
}

.react-joyride__tooltip button {
font-weight: 500 !important;
border-radius: 8px !important;
padding: 0.35rem 0.9rem !important;
}

.react-joyride__tooltip button[data-action="primary"] {
background: #e3f8ed !important;
color: #000 !important;
border: none !important;
}

.react-joyride__tooltip button[data-action="skip"] {
color: #ff5252 !important;
background: none !important;
font-weight: 600 !important;
}

.react-joyride__tooltip button[data-action="close"] {
color: #888 !important;
}

.react-joyride__tooltip-footer {
border-top: 1px solid #333 !important;
margin-top: 0.75rem !important;
padding-top: 0.75rem !important;
}

/* optional glowing spotlight */
.react-joyride__spotlight {
box-shadow: 0 0 0 1px rgba(245, 247, 246, 0.6), 0 0 12px 4px rgba(23, 26, 25, 0.4) !important;
border-radius: 5px !important;
background: transparent !important;
}



/* .landing-scroll *::-webkit-scrollbar {
width: 8px;
}
Expand Down
6 changes: 5 additions & 1 deletion app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import "./globals.css";
import TanstackProviderWrapper from "@/components/providers/TanstackProviderWrapper";
import SessionProviderWrapper from "@/components/providers/SessionProviderWrapper";
import ThemeProviderWrapper from "@/components/providers/ThemeProviderWrapper";
import { JoyrideProvider } from "./onboarding/JoyrideProvider";

const geistSans = Geist({
variable: "--font-geist-sans",
Expand Down Expand Up @@ -32,11 +33,14 @@ export default function RootLayout({
<ThemeProviderWrapper>
<SessionProviderWrapper>
<TanstackProviderWrapper>
{children}
<JoyrideProvider>
{children}
</JoyrideProvider>
</TanstackProviderWrapper>
</SessionProviderWrapper>
</ThemeProviderWrapper>
</body>
</html>
);
}

91 changes: 91 additions & 0 deletions app/onboarding/JoyrideProvider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
"use client";

import { createContext, useContext, useState, useEffect } from "react";
import { usePathname, useRouter } from "next/navigation";
import Joyride, { CallBackProps, STATUS, Step } from "react-joyride";

type JoyrideContextType = {
startTour: (tourName: string) => void;
};

const JoyrideContext = createContext<JoyrideContextType>({
startTour: () => {},
});

export const useJoyride = () => useContext(JoyrideContext);

const tours: Record<string, Step[]> = {
home: [
{ target: ".welcome-banner", content: "Welcome to DeskBuddy!" },
{ target: ".nav-dashboard", content: "You can open your dashboard here." },
],
dashboard: [
{ target: ".stress-chart", content: "This shows your stress history." },
{ target: ".music-widget", content: "Listen to calming sounds here." },
{ target: ".breathing-btn", content: "Start your breathing session here." },
],
profile: [
{ target: ".profile-picture", content: "Upload your picture here." },
{ target: ".user-details", content: "You can update your personal info here." },
{ target: ".save-profile", content: "Don’t forget to save your changes!" },
],
gpt: [
{ target: ".chat-input", content: "Type your question or message here." },
{ target: ".chat-response", content: "See DeskBuddy’s smart response here." },
{ target: ".suggestions-list", content: "Explore follow-up ideas below." },
],
mindfulness: [
{ target: ".mindfulness-video", content: "Watch mindfulness exercises here." },
{ target: ".next-session", content: "Schedule your next session here." },
],
};


export const JoyrideProvider = ({ children }: { children: React.ReactNode }) => {
const [run, setRun] = useState(false);
const [steps, setSteps] = useState<Step[]>([]);
const router = useRouter();
const pathname = usePathname();

const startTour = (tourName: string) => {
// If it's a different page, navigate first
if (!pathname.includes(tourName)) {
router.push(`/${tourName}`);
// Wait a bit for page to load before running Joyride
setTimeout(() => {
setSteps(tours[tourName] || []);
setRun(true);
}, 600);
} else {
setSteps(tours[tourName] || []);
setRun(true);
}
};

const handleJoyrideCallback = (data: CallBackProps) => {
const { status } = data;
if (status === STATUS.FINISHED || status === STATUS.SKIPPED) {
setRun(false);
}
};

return (
<JoyrideContext.Provider value={{ startTour }}>
<Joyride
steps={steps}
run={run}
continuous
showProgress
showSkipButton
callback={handleJoyrideCallback}
styles={{
options: {
zIndex: 10000,
primaryColor: "#2563eb",
},
}}
/>
{children}
</JoyrideContext.Provider>
);
};
Loading