Omarrran's picture
Add EduRecommender HuggingFace Spaces app
5bd3663
/**
* Sidebar — learner profile form with preset quick-load,
* custom profile option, and auto-mode toggle.
*/
import React from "react";
import styles from "./Sidebar.module.css";
const ALL_TAGS = [
"python", "ml", "deployment", "kubernetes", "docker",
"data-science", "pandas", "numpy", "deep-learning", "pytorch",
"neural-networks", "mlops", "ci-cd", "monitoring", "nlp",
"transformers", "bert", "llm", "prompt-engineering", "ai",
"data-engineering", "spark", "big-data", "git", "github",
"collaboration", "fastapi", "api", "backend", "aws", "sagemaker",
];
const STYLES = ["visual", "reading", "hands-on"];
const DIFFICULTIES = ["Beginner", "Intermediate", "Advanced"];
export default function Sidebar({
open,
onToggle,
profile,
onChange,
presets,
activePreset,
onPreset,
onSubmit,
loading,
autoMode,
onAutoModeChange,
}) {
const set = (key, val) => {
const updated = { ...profile, [key]: val };
// When user edits fields on a preset, switch to custom user_id
if (activePreset >= 0) {
updated.user_id = "custom";
}
onChange(updated);
};
const toggleTag = (tag) => {
const tags = profile.interest_tags || [];
set(
"interest_tags",
tags.includes(tag) ? tags.filter((t) => t !== tag) : [...tags, tag]
);
};
const toggleViewed = (id) => {
const ids = profile.viewed_content_ids || [];
set(
"viewed_content_ids",
ids.includes(id) ? ids.filter((i) => i !== id) : [...ids, id]
);
};
return (
<>
<button
className={styles.toggle}
onClick={onToggle}
aria-label="Toggle sidebar"
>
{open ? "\u2190" : "\u2192"}
</button>
<aside className={`${styles.sidebar} ${open ? styles.open : ""}`}>
<div className={styles.inner}>
<h2 className={styles.heading}>Learner Profile</h2>
{/* Auto-mode toggle */}
<button
className={`${styles.autoToggle} ${autoMode ? styles.autoOn : ""}`}
onClick={() => onAutoModeChange(!autoMode)}
>
<span className={styles.autoIcon}>{autoMode ? "\u26A1" : "\u25CB"}</span>
<span>Auto-mode</span>
<span className={styles.autoStatus}>{autoMode ? "ON" : "OFF"}</span>
</button>
{/* Presets + Custom */}
<div className={styles.presets}>
{presets.map((p, i) => (
<button
key={i}
className={`${styles.presetBtn} ${
activePreset === i ? styles.presetActive : ""
}`}
onClick={() => onPreset(i)}
>
{p.label}
</button>
))}
<button
className={`${styles.presetBtn} ${styles.customBtn} ${
activePreset < 0 ? styles.presetActive : ""
}`}
onClick={() => onPreset(-1)}
>
+ Custom Profile
</button>
</div>
<div className={styles.divider} />
{/* Name */}
<label className={styles.label}>Name</label>
<input
className={styles.input}
value={profile.name || ""}
onChange={(e) => set("name", e.target.value)}
placeholder="Your name"
/>
{/* Goal */}
<label className={styles.label}>Learning goal</label>
<textarea
className={styles.textarea}
value={profile.goal || ""}
onChange={(e) => set("goal", e.target.value)}
rows={3}
placeholder="e.g. Learn ML deployment..."
/>
{/* Learning style */}
<label className={styles.label}>Learning style</label>
<div className={styles.chips}>
{STYLES.map((s) => (
<button
key={s}
className={`${styles.chip} ${
profile.learning_style === s ? styles.chipActive : ""
}`}
onClick={() => set("learning_style", s)}
>
{s}
</button>
))}
</div>
{/* Difficulty */}
<label className={styles.label}>Preferred difficulty</label>
<div className={styles.chips}>
{DIFFICULTIES.map((d) => (
<button
key={d}
className={`${styles.chip} ${
profile.preferred_difficulty === d ? styles.chipActive : ""
}`}
onClick={() => set("preferred_difficulty", d)}
>
{d}
</button>
))}
</div>
{/* Time */}
<label className={styles.label}>
Time per day: <strong>{profile.time_per_day || 60} min</strong>
</label>
<input
type="range"
min="15"
max="120"
step="5"
className={styles.range}
value={profile.time_per_day || 60}
onChange={(e) => set("time_per_day", Number(e.target.value))}
/>
{/* Interest tags */}
<label className={styles.label}>Interest tags</label>
<div className={styles.tags}>
{ALL_TAGS.map((tag) => (
<button
key={tag}
className={`${styles.tag} ${
(profile.interest_tags || []).includes(tag)
? styles.tagActive
: ""
}`}
onClick={() => toggleTag(tag)}
>
{tag}
</button>
))}
</div>
{/* Viewed IDs */}
<label className={styles.label}>Already viewed IDs</label>
<div className={styles.chips}>
{Array.from({ length: 10 }, (_, i) => i + 1).map((id) => (
<button
key={id}
className={`${styles.chip} ${styles.chipSmall} ${
(profile.viewed_content_ids || []).includes(id)
? styles.chipActive
: ""
}`}
onClick={() => toggleViewed(id)}
>
{id}
</button>
))}
</div>
<div className={styles.divider} />
{/* Submit */}
<button
className={styles.submit}
onClick={onSubmit}
disabled={loading}
>
{loading ? (
<span className={styles.spinner} />
) : (
"Get Recommendations"
)}
</button>
</div>
</aside>
</>
);
}