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
5 changes: 3 additions & 2 deletions app/components/subjects.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ const subjects = {
"Engineering Physics",
"Engineering Graphics & Design",
"English Communication",
"Workshop Practice",
],
"Semester-2": [
"Digital Electronics & Logic Circuits",
Expand Down Expand Up @@ -79,6 +80,7 @@ const subjectCodes: Record<string, string> = {
"Engineering Graphics & Design": "egd",
"English Communication": "ec",
"Basics of Mechanical Engineering": "bme",
"Workshop Practice": "wp",

"Digital Electronics & Logic Circuits": "delc",
"OOPs with Java": "oops",
Expand Down Expand Up @@ -129,8 +131,7 @@ const subjectCodes: Record<string, string> = {
};

// Available subjects
const available = ["ep", "c", "em1", "em2", "oops", "dsc", "coa", "os", "ml", "dops", "cd", "cle", "ec", "dbms", "bme", "cns", "vlsi", "mb"];

const available = ["ep", "c", "em1", "em2", "oops", "dsc", "coa", "os", "ml", "dops", "cd", "cle", "ec", "dbms", "bme", "cns", "vlsi", "mb", "wp"];
export default function SubjectsSection() {
return (
<section id="subjects" className="px-6 pb-12 md:pt-12 text-center scroll-mt-20">
Expand Down
167 changes: 167 additions & 0 deletions app/sem1/wp/[chapter]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
import Link from "next/link";
import { Metadata } from "next";
import { Righteous } from "next/font/google";
import { Ch0Content } from "../content/chapter0";
import { ArrowBigLeft, ArrowBigRight } from "lucide-react";
import { chapters, Chapter, SubTopic } from "../constants";

function findChapterOrSubtopic(chapterId: string) {
const chapter = chapters.find((c) => c.id === chapterId);
if (chapter) return { data: chapter, isSubTopic: false, parentChapter: null };

for (const ch of chapters) {
if (ch.subTopics) {
const sub = ch.subTopics.find(
(s) => s.id === chapterId && s.isPage
) as (SubTopic & { isPage: true }) | undefined;
if (sub) return { data: sub, isSubTopic: true, parentChapter: ch };
}
}
return { data: undefined, isSubTopic: false, parentChapter: null };
}

const righteous = Righteous({
subsets: ["latin"],
weight: "400",
variable: "--font-righteous",
});

// Only ch0 is available for now — more chapters added in future PRs
const chapterComponents: Record<string, React.ComponentType> = {
ch0: Ch0Content,
};

type ChapterProps = {
params: Promise<{ chapter: string }>;
};

export async function generateMetadata({ params }: ChapterProps): Promise<Metadata> {
const { chapter: chapterId } = await params;
const { data: chapterData } = findChapterOrSubtopic(chapterId);
const title = chapterData
? `${chapterData.title} | Workshop Practice | openCSE`
: "Workshop Practice | openCSE";
return { title };
}

export default async function ChapterPage({ params }: ChapterProps) {
const { chapter: chapterId } = await params;
const { data: chapterData, isSubTopic, parentChapter } =
findChapterOrSubtopic(chapterId);

if (!chapterData) {
return (
<div className="flex flex-col items-center justify-center min-h-[50vh] text-[#e2d1c1]">
<h1 className="text-2xl font-bold mb-4">Chapter not found</h1>
<Link
href="/sem1/wp/ch0"
className="px-4 py-2 bg-[#e2d1c1] text-[#1b0d00] rounded hover:bg-[#ac9e91] transition font-bold"
>
Return to Course Outline
</Link>
</div>
);
}

const ChapterComponent = chapterComponents[chapterData.id];
let prevChapter = null;
let nextChapter = null;

if (isSubTopic && parentChapter && parentChapter.subTopics) {
const pageSubTopics = parentChapter.subTopics.filter(
(s): s is SubTopic & { isPage: true } => !!s.isPage
);
const subIndex = pageSubTopics.findIndex((s) => s.id === chapterId);
if (subIndex > 0) {
prevChapter = pageSubTopics[subIndex - 1];
} else {
prevChapter = { id: parentChapter.id, title: `Back to ${parentChapter.title}` };
}
if (subIndex < pageSubTopics.length - 1) {
nextChapter = pageSubTopics[subIndex + 1];
} else {
const parentIndex = chapters.findIndex((c) => c.id === parentChapter.id);
if (parentIndex < chapters.length - 1) nextChapter = chapters[parentIndex + 1];
}
} else {
const currentIndex = chapters.findIndex((c) => c.id === chapterId);
prevChapter = currentIndex > 0 ? chapters[currentIndex - 1] : null;
nextChapter =
currentIndex < chapters.length - 1 ? chapters[currentIndex + 1] : null;
}

return (
<div className="flex flex-col bg-[#1B0D00] min-h-full p-2 pt-16 text-[#e2d1c1]">
<div className="flex-1">
<h1 className={`text-4xl font-bold ${righteous.className} mb-2`}>
Workshop Practice
</h1>
<p className={`text-2xl mt-[-8px] ${righteous.className}`}>
{isSubTopic && parentChapter
? `${parentChapter.title} / ${chapterData.title}`
: chapterData.title}
</p>
<div className="flex justify-between mt-3">
{prevChapter ? (
<Link
href={`/sem1/wp/${prevChapter.id}`}
className="px-4 py-1 text-2xl flex items-center justify-center bg-[#e2d1c1] text-[#1b0d00] rounded hover:bg-[#ac9e91] transition"
style={{ fontFamily: "Rockwell, Serif, serif" }}
>
<ArrowBigLeft className="inline-block mr-1" /> Previous
</Link>
) : (
<div />
)}
{nextChapter ? (
<Link
href={`/sem1/wp/${nextChapter.id}`}
className="px-4 py-1 text-2xl flex items-center justify-center bg-[#e2d1c1] text-[#1b0d00] rounded hover:bg-[#ac9e91] transition"
style={{ fontFamily: "Rockwell, Serif, serif" }}
>
Next <ArrowBigRight className="inline-block ml-1" />
</Link>
) : (
<div />
)}
</div>
<hr className="my-6 border-t-3" />
{ChapterComponent ? (
<ChapterComponent />
) : (
<div className="text-center py-12 text-[#c7a669]">
<p className="text-2xl font-semibold">Coming Soon</p>
<p className="mt-2 text-lg opacity-70">
This chapter is under development. Check back soon!
</p>
</div>
)}
</div>
<div className="flex justify-between my-8">
{prevChapter ? (
<Link
href={`/sem1/wp/${prevChapter.id}`}
className="px-4 py-2 bg-[#e2d1c1] text-xl flex items-center justify-center text-[#1b0d00] rounded hover:bg-[#ac9e91] transition"
style={{ fontFamily: "Rockwell, Serif, serif" }}
>
<ArrowBigLeft className="inline-block mr-1" /> {prevChapter.title}
</Link>
) : (
<div />
)}
{nextChapter ? (
<Link
href={`/sem1/wp/${nextChapter.id}`}
className="px-4 py-2 bg-[#e2d1c1] text-xl flex items-center justify-center text-[#1b0d00] rounded hover:bg-[#ac9e91] transition"
style={{ fontFamily: "Rockwell, Serif, serif" }}
>
{nextChapter.title}{" "}
<ArrowBigRight className="inline-block ml-1" />
</Link>
) : (
<div />
)}
</div>
</div>
);
}
107 changes: 107 additions & 0 deletions app/sem1/wp/components/sidebar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
"use client";
import { Righteous } from "next/font/google";
import Link from "next/link";
import { usePathname } from "next/navigation";
import { useState, useEffect } from "react";
import { chapters } from "../constants";

const righteous = Righteous({
subsets: ["latin"],
weight: "400",
variable: "--font-righteous",
});

export default function Sidebar() {
const pathname = usePathname();
const [open, setOpen] = useState(false);

useEffect(() => {
if (window.innerWidth >= 768) {
setOpen(true);
}
}, []);

return (
<>
<div
className={`fixed inset-0 md:hidden bg-black/50 z-30 transition-opacity duration-300 ${
open ? "opacity-100" : "opacity-0 pointer-events-none"
}`}
onClick={() => setOpen(false)}
/>
<div className="flex sticky top-14 z-40 h-[calc(100vh-3.5rem)] w-[50px] md:w-auto pointer-events-none md:pointer-events-auto">
<aside
className={`h-full shrink-0 bg-[#fae8d7] text-[#1B0D00] p-0 flex flex-col transition-all duration-300 pointer-events-auto border-r-0 ${
open ? "w-64 border-r-2 md:border-r-0" : "w-0 overflow-hidden"
}`}
>
<h2
className="flex items-center text-2xl font-normal pt-3 pl-3 mb-2 bg-[#cebb9c] text-[#1B0D00] pb-2 border-b-4 border-[#1B0D00]"
style={{ fontFamily: "Rockwell, Serif, serif" }}
>
Chapters
</h2>
<ul className="flex-1 overflow-y-auto no-scrollbar space-y-0">
{chapters.map((ch) => {
const active =
pathname === `/sem1/wp/${ch.id}` ||
(ch.subTopics?.some(
(sub) => sub.isPage && pathname === `/sem1/wp/${sub.id}`
) ?? false);
return (
<li key={ch.id} className="flex flex-col">
<Link
href={`/sem1/wp/${ch.id}`}
className={`block px-3 py-2 text-xl transition ${
active ? "bg-[#fccc7e]" : "hover:bg-[#ffdda7af]"
} ${righteous.className}`}
>
{ch.title}
</Link>
{active && ch.subTopics && (
<ul className="ml-4 border-l-2 border-[#1B0D00]/20 pl-2 my-2 space-y-2">
{ch.subTopics.map((sub) => {
const subActive =
sub.isPage && pathname === `/sem1/wp/${sub.id}`;
return (
<li key={sub.id}>
<Link
href={
sub.isPage
? `/sem1/wp/${sub.id}`
: `/sem1/wp/${ch.id}#${sub.id}`
}
className={`block text-sm transition hover:font-bold ${
subActive
? "text-black font-bold"
: "text-[#3a2a14] hover:text-black"
}`}
>
{sub.title}
</Link>
</li>
);
})}
</ul>
)}
</li>
);
})}
</ul>
</aside>
<button
onClick={() => setOpen(!open)}
className="toggle-sidebar shrink-0 pointer-events-auto bg-[#ffdda7] h-full w-[50px] text-[#1B0D00] text-center font-semibold text-2xl border-l-4 rounded-r-2xl border-[#1B0D00] flex items-center justify-center transition-all duration-300 md:shadow-none"
style={{
fontFamily: "Rockwell, Serif, serif",
boxShadow: open ? "4px 0 15px rgba(0,0,0,0.1)" : "none",
}}
>
<p className="leading-5">
C<br />H<br />A<br />P<br />T<br />E<br />R<br />S
</p>
</button>
</div>
</>
);
}
20 changes: 20 additions & 0 deletions app/sem1/wp/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
export type SubTopic =
| { id: string; title: string; isPage: true }
| { id: string; title: string; isPage?: false };

export type Chapter = {
id: string;
title: string;
subTopics?: SubTopic[];
};

export const chapters: Chapter[] = [
{ id: "ch0", title: "Course Outline" },
{ id: "ch1", title: "Fitting Shop" },
{ id: "ch2", title: "Welding Shop" },
{ id: "ch3", title: "Carpentry Shop" },
{ id: "ch4", title: "Smithy Shop" },
{ id: "ch5", title: "Sheet Metal Shop" },
{ id: "ch6", title: "Foundry Shop" },
{ id: "ch7", title: "Turning Shop" },
];
36 changes: 36 additions & 0 deletions app/sem1/wp/content/chapter0.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
export function Ch0Content() {
return (
<div className="space-y-6 text-[#e2d1c1]">
<p className="text-lg leading-relaxed opacity-90">
Workshop Practice introduces first-year engineering students to hands-on
manufacturing and fabrication skills across various engineering trades. This
module covers fitting, welding, carpentry, smithy, sheet metal, foundry, and
turning shops — including theory, tools, safety practices, and viva questions.
</p>

<div className="bg-[#2a1500] rounded-xl p-5 border border-[#fccc7e]/30 space-y-3">
<h3 className="text-xl font-semibold text-[#fccc7e]">Shops at a Glance</h3>
<ul className="list-disc list-inside space-y-1 opacity-90">
<li><strong>Ch 1</strong> — Fitting Shop: hand tools, marking, filing</li>
<li><strong>Ch 2</strong> — Welding Shop: arc &amp; gas welding basics</li>
<li><strong>Ch 3</strong> — Carpentry Shop: wood joints &amp; finishing</li>
<li><strong>Ch 4</strong> — Smithy Shop: forging operations</li>
<li><strong>Ch 5</strong> — Sheet Metal Shop: bending, cutting, joining</li>
<li><strong>Ch 6</strong> — Foundry Shop: sand casting process</li>
<li><strong>Ch 7</strong> — Turning Shop: lathe machine operations</li>
</ul>
</div>

<div className="bg-[#2a1500] rounded-xl p-5 border border-[#fccc7e]/30 space-y-3">
<h3 className="text-xl font-semibold text-[#fccc7e]">What Each Shop Module Covers</h3>
<ul className="list-disc list-inside space-y-1 opacity-90">
<li>Introduction and theory</li>
<li>Important tools used</li>
<li>Safety measures</li>
<li>Labelled diagrams</li>
<li>Most asked viva questions</li>
</ul>
</div>
</div>
);
}
18 changes: 18 additions & 0 deletions app/sem1/wp/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import Navbar from "@/app/components/navbar";
import Sidebar from "./components/sidebar";

export default function WorkshopLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<div className="flex flex-col min-h-screen bg-[#1B0D00]">
<Navbar />
<div className="flex flex-1 overflow-hidden">
<Sidebar />
<main className="flex-1 overflow-y-auto p-4">{children}</main>
</div>
</div>
);
}