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
884 changes: 327 additions & 557 deletions pnpm-lock.yaml

Large diffs are not rendered by default.

36 changes: 36 additions & 0 deletions src/actions/admin/lesson.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
'use server';
import { revalidatePath } from "next/cache";
import { db } from "@/db/index";
import { lessons } from "@/db/schema";
import { lessonFormSchema } from "@/lib/validations/lesson";
import { actionClient } from "@/lib/safe-action";

export const createLessonAction = actionClient
.schema(lessonFormSchema)
.action(async ({ parsedInput }) => {
const {
title,
description,
unitId,
courseId,
mediaType,
contentUrl,
} = parsedInput;

const metadata = JSON.stringify({
title,
description: description ?? "",
});

await db.insert(lessons).values({
unitId,
mediaType, // now real value from the form
metadata,
contentUrl, // real URL from the form
// contentBlobId stays null
});

revalidatePath(`/admin/courses/${courseId}`);

return { success: true };
});
2 changes: 1 addition & 1 deletion src/actions/admin/tag.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'use server';
import { tags, users, coursesTags } from "@/db/schema";
import { type TagFormValues } from "@/lib/validations/course";
import { type TagFormValues } from "@/lib/validations/tag";
import { db } from "@/db";
import { auth } from "@/lib/auth";
import { headers } from "next/headers";
Expand Down
31 changes: 31 additions & 0 deletions src/actions/admin/units.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// src/app/admin/courses/[courseId]/lesson/create/actions.ts
'use server';

import { revalidatePath } from "next/cache";
import { db } from "@/db/index";
import { units } from "@/db/schema";
import { createUnitSchema } from "@/lib/validations/unit";
import { actionClient } from "@/lib/safe-action";

// Create unit (for the modal)
export const createUnitAction = actionClient
.schema(createUnitSchema)
.action(async ({ parsedInput }) => {
const { title, courseId } = parsedInput;
// Minimal insert: courseId (text) + title; position defaults to 1
const [unit] = await db
.insert(units)
.values({
courseId,
title,
})
.returning();

revalidatePath(`/admin/courses/${courseId}`);

return {
success: true,
unitId: unit.id,
unitTitle: unit.title,
};
});
57 changes: 57 additions & 0 deletions src/app/admin/courses/[courseId]/lesson/create/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { db } from "@/db/index";
import { units } from "@/db/schema";
import { eq } from "drizzle-orm";
import { CreateLessonForm } from "@/components/admin/CreateLessonForm";
import {
Card,
CardHeader,
CardTitle,
CardDescription,
CardContent,
} from "@/components/ui/card";

type PageProps = {
params: Promise<{ courseId: string }>;
};

export default async function CreateLessonPage({ params }: PageProps) {
const { courseId } = await params;

const courseUnits = await db
.select()
.from(units)
.where(eq(units.courseId, courseId));

return (
<div className="mx-auto flex max-w-3xl flex-col gap-6">
<div>
<h1 className="text-3xl font-semibold tracking-tight">
Create lesson
</h1>
<p className="mt-1 text-sm text-muted-foreground">
Define lesson details, add content, and assign it to a unit in this
course.
</p>
</div>

<Card className="border border-border/60 shadow-sm">
<CardHeader className="pb-4">
<CardTitle className="text-lg">Lesson details</CardTitle>
<CardDescription>
Fill out the fields below to create a new lesson. You can also
create a new unit on the fly if you need one.
</CardDescription>
</CardHeader>
<CardContent className="pt-2">
<CreateLessonForm
courseId={courseId}
initialUnits={courseUnits.map((u) => ({
id: u.id,
title: u.title ?? `Unit ${u.id}`,
}))}
/>
</CardContent>
</Card>
</div>
);
}
19 changes: 12 additions & 7 deletions src/app/admin/courses/[courseId]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
export default async function Page({
params,
}: {
params: Promise<{ courseId: string }>;

export default async function CourseIdPage({
params
}: {
params: Promise<{ courseId: string}>
}) {
const { courseId } = await params;
return <div>This is the admin course page for {courseId}</div>;
}
const { courseId } = await params;
const id = Number(courseId);

return <div className="">
Course ID: {id}
</div>
}
5 changes: 4 additions & 1 deletion src/app/admin/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import React from "react";
import AdminNavbar from "@/components/AdminNavbar";
import AdminNavbar from "@/components/admin/AdminNavbar";
import { Toaster } from "sonner"


export default function AdminLayout({
children,
Expand All @@ -14,6 +16,7 @@ export default function AdminLayout({
{/* Page content */}
<main className="flex-1 p-6">
{children}
<Toaster richColors position="top-right" />
</main>

{/* Footer */}
Expand Down
File renamed without changes.
10 changes: 9 additions & 1 deletion src/components/admin/CourseTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import {
import { getAllCourses } from "@/actions/admin/course";
import { CourseWithData } from "@/lib/types";
import { useEffect, useState } from "react";
import Link from "next/link";

const columns: ColumnDef<CourseWithData>[] = [
{
Expand Down Expand Up @@ -80,7 +81,14 @@ const columns: ColumnDef<CourseWithData>[] = [
</div>
)
},
cell: ({ row }) => <div className="text-left pl-3">{row.getValue("title")}</div>,
cell: ({ row }) => {
const course = row.original;
return (
<div className="text-left pl-3">
<Link className="hover:underline" href={`/admin/courses/${course.id}`}>{row.getValue("title")}</Link>
</div>
);
},
},
{
accessorKey: "description",
Expand Down
Loading