Skip to content
Merged
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
Binary file added public/demo.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions public/icons/devdotto.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions public/icons/github.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/icons/linkedIn.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions public/icons/x.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
16 changes: 16 additions & 0 deletions src/app/(home)/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import Header from "@/components/layout/Header";
import Footer from "@/components/layout/Footer";

export default function HomeLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return (
<>
<Header />
{children}
<Footer />
</>
);
}
14 changes: 7 additions & 7 deletions src/app/page.tsx → src/app/(home)/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@ const HomePage = () => {
return (
<main className="flex justify-center items-center ">
<div className="max-w-6xl">
<Hero/>
<div className="md:py-8 py-4">
<MainContainer/>
</div>
<div>
<Explore />
</div>
<Hero />
<div className="md:py-8 py-4">
<MainContainer />
</div>
<div>
<Explore />
</div>
</div>
</main>
);
Expand Down
44 changes: 44 additions & 0 deletions src/app/(user)/components/profile-card.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import Image from "next/image";
import { USER_SOCIALS_ICONS } from "@/constants";

export default function ProfileCard() {
return (
<div className="bg-white rounded-2xl shadow-lg py-6 px-6 md:px-12 max-w-2xl mx-auto">
<div className="flex flex-col md:flex-row justify-between items-center gap-6 md:gap-8">
{/* profile user info */}
<div className="text-center md:text-left flex-1">
<h2 className="text-2xl font-bold mb-1">Navid Abbaszedeh</h2>
<p className="text-[var(--secondary)] text-sm md:text-base">
Fullstack Engineer and Systems Architect
</p>
</div>

{/* profile user socials */}
<div className="flex flex-col items-center md:items-end gap-3">
<button className="bg-[#004715] text-white rounded-lg py-2.5 px-10 hover:bg-[#00360f] transition-colors cursor-pointer font-medium text-sm whitespace-nowrap shadow-sm hover:shadow-md">
Follow
</button>

{/* social icons */}
<div className="flex gap-3 mt-1">
{USER_SOCIALS_ICONS.map((icon) => (
<a
key={icon.id}
href="#"
className="flex items-center hover:opacity-70 transition-opacity"
>
<Image
src={icon.src}
alt={icon.label}
width={20}
height={20}
priority
/>
</a>
))}
</div>
</div>
</div>
</div>
);
}
41 changes: 41 additions & 0 deletions src/app/(user)/components/profile-tabs.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
"use client";
import { useState } from "react";
import { USER_PROFILE_TABS } from "@/constants";

export default function ProfileTabs() {
const [activeTab, setActiveTab] = useState("achievements");

return (
<div className="p-6">
{/* Tab buttons */}
<div className="flex items-center justify-between gap-2 border-b border-gray-200 pb-4 max-w-2xl mx-auto">
{USER_PROFILE_TABS.map((tab) => (
<button
key={tab.id}
onClick={() => setActiveTab(tab.id)}
className={`py-2 cursor-pointer font-medium rounded-t-lg transition ${
activeTab === tab.id
? "text-[#004715] border-b-2 border-[#004715]"
: "text-gray-600 hover:text-[#004715]"
}`}
>
{tab.label}
</button>
))}
</div>

{/* Tab content */}
<div className="mt-6 bg-[var(--foreground)] text-white p-8 rounded-2xl text-center max-w-96">
{USER_PROFILE_TABS.map((tab) => (
<div
key={tab.id}
className={`${activeTab === tab.id ? "block" : "hidden"}`}
>
<h1 className="text-2xl font-bold mb-1">{tab.heading}</h1>
<p className="leading-relaxed text-sm">{tab.content}</p>
</div>
))}
</div>
</div>
);
}
12 changes: 12 additions & 0 deletions src/app/(user)/profile/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import type { Metadata } from "next";

export const metadata: Metadata = {
title: "Frontend Advanced user profile",
description: "View user profile, achievements, badges and certifications",
};

export default function UserLayout({
children,
}: Readonly<{ children: React.ReactNode }>) {
return <section>{children}</section>;
}
37 changes: 37 additions & 0 deletions src/app/(user)/profile/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import Image from "next/image";
import ProfileCard from "@/app/(user)/components/profile-card";
import ProfileTabs from "../components/profile-tabs";

const UserProfile = () => {
return (
// black background section
<div className="relative">
<div className="bg-[var(--foreground)] h-64 relative">
{/* profile card centered on black background*/}
<div className="flex justify-center items-center h-full">
<div className="relative w-32 h-32">
<Image
src="/demo.jpeg"
alt="Profile"
fill
priority
className="object-cover rounded-full"
/>
</div>
</div>
</div>

{/* Profile info */}
<div className="max-w-6xl mx-auto">
<div className="relative -mt-12 z-10 px-4">
<ProfileCard />
</div>
</div>

{/* profile tabs */}
<ProfileTabs />
</div>
);
};

export default UserProfile;
15 changes: 5 additions & 10 deletions src/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,26 +1,21 @@
import type { Metadata } from "next";
import { inter } from "@/lib/font";
import "./globals.css";
import Header from "@/components/layout/Header";
import Footer from "@/components/layout/Footer";

export const metadata: Metadata = {
title: "Frontend Advanced",
description: "All-in-one educational platform for junior to senior frontend developers to lean advanced topics with interactive tools & hands-on coding sessions",
description:
"All-in-one educational platform for junior to senior frontend developers to lean advanced topics with interactive tools & hands-on coding sessions",
};

export default function RootLayout({
children,
}: Readonly<{
}: {
children: React.ReactNode;
}>) {
}) {
return (
<html lang="en" className={`${inter.variable}`}>
<body className={`font-sans px-5 bg-background`}>
<Header />
{children}
<Footer />
</body>
<body className={`font-sans bg-background`}>{children}</body>
</html>
);
}
63 changes: 59 additions & 4 deletions src/constants/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,62 @@ export interface SectionItem {
}

export const SECTION_CONTENT: SectionItem[] = [
{ id: 1, h1Content: "Deep dives into frameworks.", pContent: "Unpack the complexities of React, Vue, and other cutting-edge libraries with real-world scenarios.", src: "/Section-1-img.webp", alt: "This image contains the vue.js logo and a developer who is working with his laptop and exploring the framework." },
{ id: 2, h1Content: "Performance and architecture.", pContent: "Learn advanced techniques in performance optimization and scalable frontend architecture.", src: "/Section-2-img.webp", alt: "This image shows a high-level overview of a web application's architecture, with various components and layers." },
{ id: 3, h1Content: "Modern tooling mastery.", pContent: "Expert workflows covering build tools, testing, accessibility, and much more.", src: "/Section-3-img.webp", alt: "This image features modern web development coding and HTML on the sides of a laptop." },
];
{
id: 1,
h1Content: "Deep dives into frameworks.",
pContent:
"Unpack the complexities of React, Vue, and other cutting-edge libraries with real-world scenarios.",
src: "/Section-1-img.webp",
alt: "This image contains the vue.js logo and a developer who is working with his laptop and exploring the framework.",
},
{
id: 2,
h1Content: "Performance and architecture.",
pContent:
"Learn advanced techniques in performance optimization and scalable frontend architecture.",
src: "/Section-2-img.webp",
alt: "This image shows a high-level overview of a web application's architecture, with various components and layers.",
},
{
id: 3,
h1Content: "Modern tooling mastery.",
pContent:
"Expert workflows covering build tools, testing, accessibility, and much more.",
src: "/Section-3-img.webp",
alt: "This image features modern web development coding and HTML on the sides of a laptop.",
},
];

export const USER_SOCIALS_ICONS = [
{ id: 1, label: "X", src: "/icons/x.svg" },
{ id: 2, label: "Devto", src: "/icons/devdotto.svg" },
{ id: 3, label: "LinkedIn", src: "/icons/linkedIn.png" },
{ id: 4, label: "GitHub", src: "/icons/github.svg" },
];

export interface UserProfileTabItem {
id: string;
label: string;
heading?: string;
content: string;
}

export const USER_PROFILE_TABS: UserProfileTabItem[] = [
{
id: "achievements",
label: "Achievements",
heading: "System architect",
content:
"Responsible for designing and overseeing complex enterprise technical implementation with business objectives, define architectural standards, and guides development teams through strategic technology decisions",
},
{
id: "trophies",
label: "Trophies",
content: "trophies.....",
},
{
id: "badges",
label: "Badges",
content: "list of badges.....",
},
];