Implement local browser caching for shared groups and UI improvements
All checks were successful
Automated Container Build / build-and-push (push) Successful in 1m10s
All checks were successful
Automated Container Build / build-and-push (push) Successful in 1m10s
This commit is contained in:
parent
42ed0d275b
commit
7af0935657
37 changed files with 6141 additions and 411 deletions
|
|
@ -1,6 +1,6 @@
|
|||
"use client";
|
||||
|
||||
import { useState } from "react";
|
||||
import { useState, useEffect } from "react";
|
||||
import { parseAndRepairJson } from "@/lib/jsonRepair";
|
||||
import {
|
||||
flashcardImportSchema,
|
||||
|
|
@ -23,12 +23,35 @@ interface PreviewData {
|
|||
data: unknown;
|
||||
}
|
||||
|
||||
interface MaterialGroup {
|
||||
id: string;
|
||||
name: string;
|
||||
}
|
||||
|
||||
export function ImportTab({ classId, importType, onImported }: ImportTabProps) {
|
||||
const [jsonText, setJsonText] = useState("");
|
||||
const [name, setName] = useState("");
|
||||
const [preview, setPreview] = useState<PreviewData | null>(null);
|
||||
const [error, setError] = useState("");
|
||||
const [importing, setImporting] = useState(false);
|
||||
const [materialGroups, setMaterialGroups] = useState<MaterialGroup[]>([]);
|
||||
const [selectedGroupId, setSelectedGroupId] = useState<string>("");
|
||||
|
||||
useEffect(() => {
|
||||
async function fetchGroups() {
|
||||
try {
|
||||
const typeParam = importType === "flashcards" ? "DECK" : "QUIZ";
|
||||
const res = await fetch(`/api/material-groups?classId=${classId}&type=${typeParam}`);
|
||||
if (res.ok) {
|
||||
const data = await res.json();
|
||||
setMaterialGroups(data);
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("Failed to fetch material groups", err);
|
||||
}
|
||||
}
|
||||
fetchGroups();
|
||||
}, [classId, importType]);
|
||||
|
||||
function handleJsonChange(text: string) {
|
||||
setJsonText(text);
|
||||
|
|
@ -101,6 +124,7 @@ export function ImportTab({ classId, importType, onImported }: ImportTabProps) {
|
|||
classId,
|
||||
data: preview.data,
|
||||
name: name.trim(),
|
||||
groupId: selectedGroupId || null,
|
||||
}),
|
||||
});
|
||||
|
||||
|
|
@ -136,6 +160,25 @@ export function ImportTab({ classId, importType, onImported }: ImportTabProps) {
|
|||
/>
|
||||
</div>
|
||||
|
||||
{/* Group field */}
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-text-secondary mb-1.5">
|
||||
Group (Optional)
|
||||
</label>
|
||||
<select
|
||||
value={selectedGroupId}
|
||||
onChange={(e) => setSelectedGroupId(e.target.value)}
|
||||
className="w-full px-3.5 py-2.5 rounded-lg border border-border bg-bg-surface-alt/50 text-text-heading focus:outline-none focus:ring-2 focus:ring-primary/30 focus:border-primary transition-all duration-200"
|
||||
>
|
||||
<option value="">Uncategorized</option>
|
||||
{materialGroups.map((group) => (
|
||||
<option key={group.id} value={group.id}>
|
||||
{group.name}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
{/* JSON paste area */}
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-text-secondary mb-1.5">
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue