Initial commit: standalone quiz-testing system
Full-stack F# (Domain/Server/Client via Fable+Elmish+Feliz), PostgreSQL persistence via Dapper, Docker Compose deployment. Student quiz-taking flow with time-limit enforcement and focus-loss tracking, Teacher question bank and quiz builder with results analytics, Admin user management.
This commit is contained in:
50
src/Client/Features/Teacher/Home/State.fs
Normal file
50
src/Client/Features/Teacher/Home/State.fs
Normal file
@@ -0,0 +1,50 @@
|
||||
module Client.Features.Teacher.Home.State
|
||||
|
||||
open Elmish
|
||||
open Domain
|
||||
open Client.Features
|
||||
open Client.Features.Teacher.Home.Types
|
||||
|
||||
/// `role` decides whether the Admin-only "Пользователи" tab is shown/loaded —
|
||||
/// Teacher and Admin otherwise share this exact same page (see DESIGN.md §2:
|
||||
/// Admin = Teacher + user management).
|
||||
let init (role: Role) : Model * Cmd<Msg> =
|
||||
let questionsModel, questionsCmd = Teacher.Questions.State.init ()
|
||||
let testsModel, testsCmd = Teacher.Tests.State.init ()
|
||||
|
||||
let usersCmd =
|
||||
match role with
|
||||
| Admin -> Cmd.map UsersMsg (Cmd.ofMsg Admin.Users.Types.LoadUsers)
|
||||
| Teacher
|
||||
| Student -> Cmd.none
|
||||
|
||||
{ Tab = QuestionsTab
|
||||
Role = role
|
||||
Questions = questionsModel
|
||||
Tests = testsModel
|
||||
Users = Admin.Users.Types.empty },
|
||||
Cmd.batch [ Cmd.map QuestionsMsg questionsCmd; Cmd.map TestsMsg testsCmd; usersCmd ]
|
||||
|
||||
let update (token: string option) (msg: Msg) (model: Model) : Model * Cmd<Msg> =
|
||||
match msg with
|
||||
| SwitchTab tab -> { model with Tab = tab }, Cmd.none
|
||||
| QuestionsMsg(Teacher.Questions.Types.TopicCreated topic as subMsg) ->
|
||||
let m, cmd = Teacher.Questions.State.update token subMsg model.Questions
|
||||
|
||||
{ model with
|
||||
Questions = m
|
||||
// Questions and Tests keep independent `Topics` lists (own VSA
|
||||
// slices, own `LoadTopics` on init) — a topic created in one
|
||||
// must be mirrored into the other, or the quiz question-picker
|
||||
// never sees topics added after the page first loaded.
|
||||
Tests = { model.Tests with Topics = model.Tests.Topics @ [ topic ] } },
|
||||
Cmd.map QuestionsMsg cmd
|
||||
| QuestionsMsg subMsg ->
|
||||
let m, cmd = Teacher.Questions.State.update token subMsg model.Questions
|
||||
{ model with Questions = m }, Cmd.map QuestionsMsg cmd
|
||||
| TestsMsg subMsg ->
|
||||
let m, cmd = Teacher.Tests.State.update token subMsg model.Tests
|
||||
{ model with Tests = m }, Cmd.map TestsMsg cmd
|
||||
| UsersMsg subMsg ->
|
||||
let m, cmd = Admin.Users.State.update token subMsg model.Users
|
||||
{ model with Users = m }, Cmd.map UsersMsg cmd
|
||||
Reference in New Issue
Block a user