DocDoeAI / src /components /learn-anything /LearnAnythingQueryBox.tsx
asnannp's picture
deploy: sync backend to Space root (learn-lesson HF cache fix)
65d68f5
Raw History Blame Contribute Delete
9.63 kB
"use client";
import { useId } from "react";
import type { LearningPathVariant, LearnAnythingFormData } from "./learnAnythingTypes";
const TUITION_EXAMPLE_CHIPS = [
"Teach me +2 Physics motion in a straight line",
"Explain Kerala Plus Two Chemistry electrochemistry",
"Teach Boolean logic from zero",
"Revise Class 10 Maths quadratic equations",
];
const GENERAL_EXAMPLE_CHIPS = [
"Build a zero to advanced Python curriculum",
"Teach me machine learning from scratch",
"Create a business basics learning path",
"Learn AI agents with projects",
];
const CLASS_OPTIONS = ["Class 8", "Class 9", "Class 10", "Plus One / Grade 11", "Plus Two / Grade 12"];
const SYLLABUS_OPTIONS = ["Kerala HSE", "CBSE", "ICSE", "State Board"];
const SUBJECT_OPTIONS = ["Physics", "Chemistry", "Mathematics", "Biology", "Computer Science", "Social Science"];
const DAILY_TIME_OPTIONS = ["30 minutes", "1 hour", "1.5 hours", "2 hours", "Exam-eve emergency mode"];
const TUITION_GOAL_OPTIONS = [
{ value: "full-marks", label: "Full marks" },
{ value: "a-plus", label: "A+" },
{ value: "strong-basics", label: "Strong basics" },
{ value: "pass", label: "Pass" },
{ value: "revision", label: "Revision" },
{ value: "exam-rescue", label: "Exam rescue" },
];
const GENERAL_GOAL_OPTIONS = [
{ value: "zero-to-advanced", label: "Zero to advanced" },
{ value: "job-skill", label: "Practical job skill" },
{ value: "project-based", label: "Project-based learning" },
{ value: "exam-or-interview", label: "Exam or interview prep" },
{ value: "quick-foundation", label: "Quick foundation" },
];
const LEVEL_OPTIONS = [
{ value: "beginner", label: "Beginner" },
{ value: "basic", label: "Basic" },
{ value: "average", label: "Average" },
{ value: "intermediate", label: "Intermediate" },
{ value: "advanced", label: "Advanced" },
];
interface LearnAnythingQueryBoxProps {
formData: LearnAnythingFormData;
onChange: (data: LearnAnythingFormData) => void;
variant?: LearningPathVariant;
}
export function LearnAnythingQueryBox({ formData, onChange, variant = "general" }: LearnAnythingQueryBoxProps) {
const id = useId();
const isTuition = variant === "tuition";
const examples = isTuition ? TUITION_EXAMPLE_CHIPS : GENERAL_EXAMPLE_CHIPS;
const goalOptions = isTuition ? TUITION_GOAL_OPTIONS : GENERAL_GOAL_OPTIONS;
const updateField = (field: keyof LearnAnythingFormData, value: string) => {
onChange({ ...formData, [field]: value });
};
return (
<div className="w-full space-y-4">
<div className="relative">
<label htmlFor={`${id}-query`} className="sr-only">
{isTuition ? "What school concept do you want to study?" : "What skill or topic do you want to learn?"}
</label>
<textarea
id={`${id}-query`}
value={formData.query}
onChange={(e) => updateField("query", e.target.value)}
placeholder={
isTuition
? "Tell DocDoe your class, syllabus, subject, chapter, or doubt..."
: "Tell DocDoe the skill, topic, project, or outcome you want..."
}
className="w-full min-h-[120px] resize-none rounded-2xl border border-white/10 bg-white/[0.03] px-5 py-4 text-white placeholder:text-white/45 focus:outline-none focus:ring-2 focus:ring-white/20 focus:border-transparent transition-all scrollbar-thin scrollbar-thumb-white/20 scrollbar-track-transparent"
aria-describedby={`${id}-description`}
/>
<p id={`${id}-description`} className="sr-only">
{isTuition
? "Enter a school topic, subject, chapter, doubt, or exam goal."
: "Enter a skill, topic, project, or learning goal."}
</p>
</div>
{formData.query.length === 0 && (
<div className="flex flex-wrap gap-2">
{examples.map((example) => (
<button
key={example}
type="button"
onClick={() => updateField("query", example)}
className="rounded-lg border border-white/15 bg-white/[0.04] px-3 py-1.5 text-sm text-white/70 hover:bg-white/[0.08] hover:border-white/25 transition-colors"
>
{example}
</button>
))}
</div>
)}
{isTuition ? (
<div className="grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3">
<SelectField
id={`${id}-class`}
label="Class"
value={formData.classLevel}
placeholder="Class not set"
options={CLASS_OPTIONS}
onChange={(value) => updateField("classLevel", value)}
/>
<SelectField
id={`${id}-syllabus`}
label="Syllabus / Board"
value={formData.syllabus}
placeholder="Syllabus not set"
options={SYLLABUS_OPTIONS}
onChange={(value) => updateField("syllabus", value)}
/>
<SelectField
id={`${id}-subject`}
label="Subject"
value={formData.subject}
placeholder="Subject not set"
options={SUBJECT_OPTIONS}
onChange={(value) => updateField("subject", value)}
/>
<TextField
id={`${id}-chapter`}
label="Chapter / Topic"
value={formData.chapter}
placeholder="e.g. Ray Optics"
onChange={(value) => updateField("chapter", value)}
/>
<TextField
id={`${id}-exam-date`}
label="Exam Date"
value={formData.examDate}
type="date"
onChange={(value) => updateField("examDate", value)}
/>
<SelectField
id={`${id}-daily-time`}
label="Daily Study Time"
value={formData.dailyStudyTime}
placeholder="Time not set"
options={DAILY_TIME_OPTIONS}
onChange={(value) => updateField("dailyStudyTime", value)}
/>
<SelectField
id={`${id}-current-level`}
label="Current Level"
value={formData.currentLevel}
placeholder="Level not set"
options={LEVEL_OPTIONS}
onChange={(value) => updateField("currentLevel", value)}
/>
<TextField
id={`${id}-weak-topics`}
label="Weak Topics"
value={formData.weakTopics}
placeholder="e.g. derivations, units"
onChange={(value) => updateField("weakTopics", value)}
/>
</div>
) : (
<div className="grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3">
<TextField
id={`${id}-subject`}
label="Skill Area"
value={formData.subject}
placeholder="e.g. Python, ML, business"
onChange={(value) => updateField("subject", value)}
/>
<SelectField
id={`${id}-current-level`}
label="Current Level"
value={formData.currentLevel}
placeholder="Level not set"
options={LEVEL_OPTIONS}
onChange={(value) => updateField("currentLevel", value)}
/>
<SelectField
id={`${id}-daily-time`}
label="Daily Study Time"
value={formData.dailyStudyTime}
placeholder="Time not set"
options={DAILY_TIME_OPTIONS.filter((option) => option !== "Exam-eve emergency mode")}
onChange={(value) => updateField("dailyStudyTime", value)}
/>
</div>
)}
<SelectField
id={`${id}-goal`}
label="Goal"
value={formData.goal}
placeholder="Goal not set"
options={goalOptions}
onChange={(value) => updateField("goal", value)}
/>
</div>
);
}
function fieldClassName() {
return "w-full rounded-xl border border-white/10 bg-white/[0.03] px-4 py-2.5 text-white placeholder:text-white/45 focus:outline-none focus:ring-2 focus:ring-white/20 focus:border-transparent transition-all";
}
function FieldLabel({ id, label }: { id: string; label: string }) {
return (
<label htmlFor={id} className="block text-sm font-medium text-white/70 mb-1">
{label}
</label>
);
}
function SelectField({
id,
label,
value,
placeholder,
options,
onChange,
}: {
id: string;
label: string;
value: string;
placeholder: string;
options: Array<string | { value: string; label: string }>;
onChange: (value: string) => void;
}) {
return (
<div>
<FieldLabel id={id} label={label} />
<select id={id} value={value} onChange={(e) => onChange(e.target.value)} className={fieldClassName()}>
<option value="">{placeholder}</option>
{options.map((option) => {
const value = typeof option === "string" ? option : option.value;
const label = typeof option === "string" ? option : option.label;
return (
<option key={value} value={value}>
{label}
</option>
);
})}
</select>
</div>
);
}
function TextField({
id,
label,
value,
placeholder,
type = "text",
onChange,
}: {
id: string;
label: string;
value: string;
placeholder?: string;
type?: "text" | "date";
onChange: (value: string) => void;
}) {
return (
<div>
<FieldLabel id={id} label={label} />
<input
id={id}
value={value}
type={type}
placeholder={placeholder}
onChange={(e) => onChange(e.target.value)}
className={fieldClassName()}
/>
</div>
);
}