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
41 changes: 0 additions & 41 deletions drizzle/0001_add_gamification.sql

This file was deleted.

6 changes: 0 additions & 6 deletions drizzle/0002_add_teacher_verification.sql

This file was deleted.

5 changes: 0 additions & 5 deletions drizzle/meta/_journal.json

This file was deleted.

40 changes: 20 additions & 20 deletions src/app/api/chat/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,27 +28,15 @@ export async function POST(req: Request) {
return new Response("Note ID is required", { status: 400 });
}

// Save user message + award points for meaningful chat
// Save user message + award points for meaningful chat
const lastMessage = messages[messages.length - 1];
if (lastMessage?.role === "user") {
const lastMessageContent = lastMessage.parts
.filter((p) => p.type === "text")
.map((p) => p.text)
.join("");

// Fire and forget, or we could await if needed.
// For now, just calling them to resolve unused variable lint error.
void caller.chat.onStudentMessage({
noteId,
content: lastMessageContent,
});

void caller.activity.ping({
noteId,
eventType: "chat",
});
}
const shouldTrack =
lastMessage?.role === "user" && lastMessage.parts?.length;
const lastMessageContent = shouldTrack
? lastMessage.parts
.filter((p) => p.type === "text")
.map((p) => p.text)
.join("")
: "";

const modelMessages = await convertToModelMessages(messages);

Expand Down Expand Up @@ -76,6 +64,18 @@ ${textContent ?? "No text content available."}
noteId: noteId,
});
}

if (shouldTrack && lastMessageContent) {
void caller.chat.onStudentMessage({
noteId,
content: lastMessageContent,
});

void caller.activity.ping({
noteId,
eventType: "chat",
});
}
},
});

Expand Down
10 changes: 9 additions & 1 deletion src/app/api/uploadthing/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,15 @@ export const ourFileRouter = {
});
}

if (existingCourse.teacherId !== context.session?.user.id) {
const requester = await caller.user.getById({
id: context.session?.user.id ?? "",
});

const isOwner =
existingCourse.teacherId === context.session?.user.id;
const isAdmin = requester?.role === "admin";

if (!isOwner && !isAdmin) {
// eslint-disable-next-line @typescript-eslint/only-throw-error
throw new UploadThingError({
code: "FORBIDDEN",
Expand Down
2 changes: 1 addition & 1 deletion src/components/layout/main-layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export default function MainLayout({
<div className="min-h-screen bg-slate-950 text-slate-50 selection:bg-indigo-500/30">
<Navbar />

<main className="container mt-12 mx-auto px-4 pb-12">
<main className="container mx-auto mt-12 px-4 pb-12">
{children}
</main>
</div>
Expand Down
2 changes: 0 additions & 2 deletions src/modules/admin/admin-panel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@ export default function AdminPanel() {
const [email, setEmail] = useState("");
const [searchedEmail, setSearchedEmail] = useState<string | null>(null);

type UserByEmail = RouterOutputs["user"]["getByEmail"];

const userQuery = api.user.getByEmail.useQuery(
{ email: searchedEmail ?? "" },
{ enabled: !!searchedEmail }
Expand Down
59 changes: 59 additions & 0 deletions src/modules/course/features/confirm-delete-dialog.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
"use client";

import { Button } from "~/components/ui/button";
import {
Dialog,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
} from "~/components/ui/dialog";

interface ConfirmDeleteDialogProps {
open: boolean;
title: string;
description: string;
confirmLabel?: string;
isPending?: boolean;
onConfirm: () => void;
onOpenChange: (open: boolean) => void;
}

export function ConfirmDeleteDialog({
open,
title,
description,
confirmLabel = "Delete",
isPending,
onConfirm,
onOpenChange,
}: ConfirmDeleteDialogProps) {
return (
<Dialog open={open} onOpenChange={onOpenChange}>
<DialogContent className="sm:max-w-md">
<DialogHeader>
<DialogTitle>{title}</DialogTitle>
<DialogDescription>{description}</DialogDescription>
</DialogHeader>
<DialogFooter>
<Button
variant="outline"
onClick={() => onOpenChange(false)}
type="button"
>
Cancel
</Button>
<Button
variant="destructive"
onClick={onConfirm}
disabled={isPending}
type="button"
>
{isPending ? "Deleting..." : confirmLabel}
</Button>
</DialogFooter>
</DialogContent>
</Dialog>
);
}
Loading