Reference for the iOS and Android teacher app as of version 1.7.3: screens, flows, gaps against teacher.flyer.us, known issues, the engineering setup, and a proposed UI redesign.
Written in response to these requests of 15/10/2026:
Hiện tại đã có documents cho Teacher Mobile App chưa
could you build PRD show what we have at the moment at roadmap.flyer.vn/teacher-mobile-app
Đề xuất cho anh một bản UI/UX tốt hơn cho Teacher Mobile App nhé https://roadmap.flyer.vn/teacher-mobile-app/#screens(16/10/2026, answered in the UI proposal tab)
Drafted by an AI assistant in one working session. Before this page, the app had no product documentation: the repository README is an unedited GitLab template, the docs/ folder holds one design spec (Assign Test share via Zalo, 22/07/2026), and the Notion page "FLYER Teacher App" (06/2023) is a sales paragraph.
Sources for the UI proposal: the 35 screenshots on the Screens tab; the API schema generated from production on 15/10/2026 (for which operations already exist); platform figures from earlier read-replica studies: /teacher-top5 (1,131 active teachers, 01/06–31/08/2026: 86% desktop, 11% phone browser, 2.4% app sessions; 16.3% of assignments with no submission; AI records linked to a student 5 of 620 speaking, 4 of 465 writing) and /assignment-v2 (19/09/2026: 49.9% submission rate, 97.1% of assignments to whole classes, 40.6% with a due date). For section 5: the Bingo AI Co-Teacher PRD and its production notes of 14/10/2026 (cold-start suggestions, duplicate names, pause default), and the v4 API types in partner-web-main (src/api/__generated__/openapi-v4.ts, @ 587e719).
Sources: source code of mobile-partner branch dev @ d0233fd (14/10/2026), read by three read-only code agents and checked by hand; partner-web-main @ 587e719 (06/10/2026) for the web comparison; App Store lookup API for store facts; 35 screenshots taken on 15/10/2026 from a local Debug build of the same commit on the iOS Simulator (iPhone 17 Pro), signed in with a real teacher account.
Limits:
api.flyer.us). Screens were only viewed; nothing was created, assigned or deleted.| Role | Entry | What the role sees |
|---|---|---|
| Teacher | Select role → sign in | Five tabs below. Gated by teacher verification, teacher profile and current school. |
| Parent | Select role, or "Switch to parents profile" in the teacher menu | One child at a time: performance, test history, weekly report, tuition bills with bank QR. |
| Student | None | Not supported. Students use the FLYER student app. |
Tabs show icons only; the labels exist in code but are not rendered.
| Area | What exists | State |
|---|---|---|
| Sign in / sign up | Phone or username + password, Google, Apple (iOS). Sign-up by phone + OTP. Forgot password by OTP. One active session per account. | Live |
| Onboarding | Name, optional email and phone, first class, class code and invite link. Unverified teachers are sent to a Google Form. | Live |
| Dashboard | Classes, students, completed tests, study hours (default last 30 days; 9 preset ranges plus custom); study-time chart; top 10 classes by study time and accuracy; referral banner. | Live |
| Classes | Create (General, Placement test, IELTS), edit, delete; class dashboard with charts by test level; per-student report; invite by link or email. | Live |
| Students | List with filter, summary sheet, performance overview, test history, test result. Students join through the invite link; teachers cannot create, edit or delete student accounts. | Live |
| Assign tests | 3 steps: pick test (8 types, search, filters), pick classes or students, options (start, deadline, hide answers, exam mode, auto-lock, share via Zalo). Progress per assignment. | Live |
| Explore | Test library by CEFR level with Free/Premium tags, filters, preview, assign. | Live |
| Program | FLYER Original, school and own programs; book → unit → lesson → assign. Browse only. | Live |
| Writing AI | IELTS Task 1/2, KET Part 6/7, PET, Flyers. Typed essay or images; score, criteria, corrections, samples. History list. | Live |
| Grade from photos | Up to 5 photos of handwritten work from camera or gallery. App-only. | Live |
| Speaking AI | Record up to 119 s; pronunciation, fluency, grammar, vocabulary; CEFR, IELTS, TOEIC, PTE, TOEFL estimate. Daily limit set on the server. Audio-file upload is commented out. | Live |
| Notifications | In-app list (Class / FLYER News), school and class requests to accept or decline, push via Firebase with topics per role. | Live |
| Affiliate | Referral code and link, share, referred students, reward (50,000 VND per student upgrade). | Live |
| Settings | Edit profile, change password, switch school, language (EN/VI), terms, delete account, help (phone call), report bug (email). | Live |
| Parent mode | Child switcher; report, history, weekly report, tuition bills with bank-transfer QR. | Live |
| What's new | Popup once per app version, teachers only. | Live |
| Maintenance / forced update | Remote Config switches: maintenance overlay, minimum app version. | Live |
| In-app purchase | None. No paywall or subscription screen. | None |
| Product analytics | None. No custom events; only Firebase automatic events, if any. | None |
Select a screen to enlarge it. Each view can be shared by link (#screens/<area>). Chips show the route name in code.
16/10/2026 (2): Bingo AI Co-Teacher added (section 5, 2 new screens, entry points on Today, Class, Student and Assignments). 16/10/2026: first version: diagnosis, navigation change, 13 clickable screens, build notes, phasing.
| Problem | Seen on | Evidence |
|---|---|---|
| Home reports volume, not work to do | Home | 16.3% of assignments get no submission on the platform; no app screen flags them. |
| Icon-only tabs; tools hidden in home tiles | Home | Tab labels exist in code but are not rendered. Explore, Program and the AI tools open only from home tiles. |
| Numbers contradict each other | Students, Parent | 8 number issues across 9 screens, listed in the Issues tab. |
| After assigning, nothing can be done | Assign | Remind, extend and manual scoring exist in the API; the app calls none of them. |
| AI grading sits outside the class | AI grading | On the platform, 5 of 620 speaking and 4 of 465 writing records are linked to a student. |
| Long lists of label–value rows | Classes | The class dashboard stacks two 11-row level tables; a writing report is one block of text. |
| Filters before content | Assign, Content | Assign step 1 opens on three empty dropdowns. Explore does not start from the level of the teacher's classes. |
| Alerts are not grouped | Menu | 212 "Class Target!" items in the Class tab, one per student, with no action besides opening. |
| Secondary actions look primary | Menu | "Switch to parents profile" and "Log out" are full-width filled buttons; help is a phone call. |
Each phone is a working 390×844 layout. Tap inside it: tabs, the + button, Remind, Extend and Grade respond. Compare puts today's screen next to the proposal.
Live on the web (production capture 14/10/2026, PRD); not in the app. Approving a weekly queue takes a minute between lessons, so it fits the app's check-and-nudge role. Open the Bingo screens.
| Where | What the teacher sees | Against the Bingo PRD mobile design |
|---|---|---|
| Today | "6 suggestions to review" with Review and Approve all | Same home banner |
| Suggestions | Per student: level, reason, two tests, Approve / Change / Skip; paused students shown apart | Same vertical cards with buttons, no swiping |
| Class | "Bingo AI · Suggest mode" row opening the queue and the class settings | Same settings per class |
| Student | Skill bars from single-skill tests, next Bingo test | Differs bars instead of a 4-axis radar: exact values, and a missing skill reads as "—" instead of a broken shape |
| Assignments | Tests sent by Bingo carry a "Bingo" label in the same list | New answers the PRD's open question on labelling |
| Tab bar | No Bingo tab | Same no sixth tab; the menu shortcut moves to Today and Class |
| API field | Shown as |
|---|---|
reason_code = WEAK_SKILL + target_skill | "Weakest skill: Speaking · 55%" |
reason_code = NO_DATA_FOR_SKILL | "No graded Writing yet" |
target_skill_tied = true | "Skills are level · Listening picked" |
skipped_for_unfinished = true | "Paused: 2 Bingo tests not done yet" with Remind |
assign_at, assign_weekdays | "Go out Mon 20 Oct, 17:00": approval does not send at once |
mode, weekly_target, level_band, max_duration_minutes, skip_when_unfinished, source_school | The six rows of the settings screen |
The PRD's example reasons ("4 of 5 speaking tests lost points on long vowels") are richer than the API's reason codes. The mobile screens show only what the API returns.
| Question | Observation | Suggested answer |
|---|---|---|
| Student with no graded work | Production suggested the same two tests to three such students, citing "skills are level" | For NO_HISTORY, suggest a placement test instead |
| Pause when unfinished | PRD rule: pause at 2 unfinished tests. Production default: never pause | Default to 2, as the PRD says |
| Automatic mode from the phone | Switching to Automatic sends tests without review | Allow, with a confirmation that names the class and the weekly count |
| Students with the same name | Two "Hoàng Nghiệp" in one production class | Show the username under the name |
| Screen | Change | Backend |
|---|---|---|
| Tab bar | Labels, 4 tabs and a + button | None |
| Today | Rank tests nobody started, answers to grade, quiet classes | None existing assignment and class queries; a summary query is optional |
| Assignments | Group by state; Remind; Extend | Exists partnerViewerAssignTestRemindStudent, …RemindParent, partnerAssignTestUpdate (end date); unused by the app |
| Assignment detail | Three groups, Grade, weak-question banner | Exists PartnerAssignTestProfiles, partnerViewerAssignTestScoreUserAttempts |
| Assign a test | One screen, defaults, options folded | None same PartnerAssignTestCreate |
| Bingo AI | Suggestion queue, class settings, skills on the student screen, label in Assignments | Exists 8 REST endpoints under /v4/teacher/bingo/ in the web's v4 client; the app needs a v4 client (it has v3 only) |
| Grade with AI draft | AI drafts a score on the exam scale for a submitted answer; the teacher confirms | Small AI inputs already take learnerProfileId; running AI on an assignment answer needs a hook |
| Grade from photos | Pick the student on the same screen | None send learnerProfileId |
| Class | Merge dashboard, students and assignments; one date range | None existing queries with one date input |
| Student | Accuracy in %, hours with one decimal, dated chart | Confirm the unit behind "2.19" |
| Library | Explore and Program in one tab, filtered by class level | None |
| Notifications | Decisions first; repeated alerts grouped | None grouping on the client |
| Profile | Plain list; in-app feedback with screenshot | Small feedback endpoint |
| Phase | Scope | Backend | Rough size |
|---|---|---|---|
| 1 · Quick wins | Labelled tab bar and + button; one number format and stated ranges; Profile and Notifications cleanup; AI tools send the student | None | 2–3 weeks |
| 2 · Assignment loop | Today, Assignments tracking, Remind, Extend, detail groups, manual grading, Bingo suggestion queue | None; existing mutations and the v4 Bingo endpoints | 3–4 weeks |
| 3 · Hubs | Class hub, Library, one-screen assign, AI draft for submitted writing, Bingo class settings | Small hook for AI on answers | 4–5 weeks |
Product events (/tracking-events, surface app_teacher) ship with phase 1, so phases 2 and 3 can be judged on data.
| Question | Metric | Now | Target |
|---|---|---|---|
| Do teachers act from the app? | App sessions with an action (remind, extend, grade, assign) | Not measured | Baseline in 4 weeks |
| Does the loop save assignments? | Submission rate, reminded vs not reminded | 49.9% overall | +10 points when reminded |
| Is AI grading in the class? | AI records linked to a student | Under 1% | Over 60% |
| Is the Bingo queue handled? | Suggestions approved, changed or skipped before the send time | Not measured | Over 80% |
| Do the numbers agree? | Open number issues from the Issues tab | 8 | 0 |
| Assumption | How to test |
|---|---|
| Teachers open the app between lessons to check and nudge, not to build content. | 5 teacher interviews with the prototype; session data after phase 1 |
| Reminders help more than they annoy. | Once per student per 24 hours, opt-in per class; compare reminded and not reminded |
| A due date on by default is acceptable (40.6% of assignments set one today). | Share of teachers who clear the default in phase 2 |
| Teachers will confirm an AI draft instead of grading from scratch. | Share of drafts confirmed unchanged, edited, or discarded |
| Flow | Steps |
|---|---|
| Sign in |
|
| Sign up |
|
| After sign-in | Not verified as teacher → Google Form · no teacher profile → onboarding · no current school → pick a school · otherwise the five tabs. A sign-in on another device signs this one out. |
| Flow | Steps |
|---|---|
| Create class | Type (General, Placement test, IELTS with target score) → level → name. |
| Get students in | No manual add. Share the join link (school domain + class code, e.g. tung.flyer.us/join-class?classCode=…), send the email template, or invite by email address. Students join from their own app. |
| Check a student | Students tab or class → student card → summary sheet → performance (tests, accuracy, time) and test history → test result. |
| Step | What the teacher does |
|---|---|
| 1 · Test | Resource (All, FLYER tests, school domains), type, skill, level, or search. 8 types: Reading & Listening, Speaking, Writing, Mini, Practice quiz, IELTS, Discussion, Study. Can start pre-filled from Explore or Program. |
| 2 · Who | Whole classes or individual students. Classes that already have the test are marked. |
| 3 · Options | Start time · deadline (off by default; +7 days when switched on) · hide answers · exam mode · auto-lock after deadline · share via Zalo with message preview. |
| Done | Summary screen. With Zalo on: system share sheet (pick Zalo, then the group) or copy message. |
| Follow up | Assigned test → progress per student (first/last submit, attempts, highest score, average time) and answer overview. No manual grading in the app. |
Result screens: IELTS speaking and KET/PET speaking or writing open as web views; all other results are native screens.
| Tool | Input | Output |
|---|---|---|
| Writing AI | Task type, question, essay text; optional images (1 for IELTS, up to 3 otherwise, 3 MB each) | Score, criteria analysis, suggestions, corrections, sample answers, vocabulary |
| Grade from photos | Up to 5 photos from camera or gallery; task type incl. General | Same report, plus an image viewer |
| Speaking AI | Free recording up to 119 s, pause and resume, no prompt | Overall and 4 sub-scores, exam-scale estimates, transcript with word audio |
Welcome screen → parent name (first time) → child switcher → four tabs: Report (tests assigned, accuracy, study hours, progress, chart) · History · Weekly (submissions, study time, self-study, skill bars versus last week, written summary) · Billing (unpaid and paid tuition, overdue popup, bank QR to save or share). Push notifications open the weekly report or a bill.
Rows follow the 20 areas of the FLYER Teacher PRD catalog, then other web features.
| Area | Web | App | What the app lacks |
|---|---|---|---|
| Reports | Yes | Partial | 4 headline numbers, a study-time chart and rankings; limited drill-down (completed-test list, class dashboard). No daily, weekly or monthly reports, no export. |
| Explore tests | Yes | Yes | No playlists; no worksheet preview or print. |
| Program | Yes | Partial | Browse and assign only. No create, edit or AI-generate; no class progress. |
| Auto-assign | Yes | No | Whole feature. |
| Placement test | Yes | Partial | Has the class type and the new-students list. Cannot send a placement link or see results. |
| AI grading | Yes | Yes | No audio-file upload for speaking. |
| AI teaching assistant | Yes | No | Whole feature. |
| Create test | Yes | No | Whole feature (all builders). |
| My library | Yes | No | Own tests reachable only through "Choose resource" when assigning. |
| Exam management | Yes | No | Whole feature. |
| Class management | Yes | Partial | Overview and student report only; 8 of 10 web class tabs missing (3 of the 10 appear on the web only when enabled per school). No co-teachers, no pinning. |
| Students | Yes | Partial | No create, edit, delete, password reset or transfer. Only email invites and approval of leave-class requests. |
| Assign homework | Yes | Yes | No manual grading; "needs grading" is shown but cannot be acted on. |
| Rewards | Yes | No | Whole feature. |
| Attendance | Yes, per-school setting | No | Whole feature. |
| Gifts | Prototype only | No | Not live on either platform. |
| Challenges | Yes | No | Whole feature. |
| Online teaching | Yes, per-school setting | No | Whole feature. |
| Finance / tuition | Yes | Partial | Parents can view bills and get a bank-transfer QR; teachers cannot create bills or track payments. |
| Settings | Yes | Partial | Personal settings only. No school accounts, roles, teacher invites, courses, store or theme. |
| Other web features | |||
| Bingo AI Co-Teacher | Yes | No | Whole feature. |
| Games | Yes | No | Whole feature. |
| Plans and diamonds | Yes | No | No plan, billing or diamond screens. |
| School admin, white-label | Yes | Partial | Switch school only. No school branding or portal numbers. |
| Onboarding | Yes | Yes | No quick-start checklist or guided tours. |
| Notifications | Yes | Yes | None; the app adds push. |
| What's new | Yes | Yes | Popup per version only, no history. |
| Feature | Note |
|---|---|
| Grade from photos | In-app camera, up to 5 photos. The web accepts uploaded image files but has no camera flow. |
| Push notifications | Firebase topics per role; tap opens a test result, weekly report or bill. |
| Teacher ⇄ parent switch | One tap in the menu, same account. The parent role itself also exists on the web. |
| Sign in with Apple | iOS only. |
| Delete account | In-app deletion, required by the App Store. |
"Seen" = visible in the screenshots on the Screens tab. "Code" = found by reading the source; not reproduced on a device.
| Issue | Where | Basis | Level |
|---|---|---|---|
| Accuracy shown as 2.19 with a "(%)" label for a student with 110 completed tests; the unit is unclear. | Student sheet, student performance | Seen | Medium |
| One student, two test-time values: 9,98 hours on the card and in performance, 09:00:53 in the summary sheet. | Students tab, student sheet | Seen | Medium |
| Student chart dates are day/month without year and out of order (05/08 … 22/12, 23/07, 07/01, 02/05). | Student performance | Seen | Medium |
| Same class, same screen: 150 completed tests and 33.73 h (last 30 days) versus 144 and 32.53 h (15/09–15/10). | Class dashboard | Seen; ranges differ, needs check | Check |
| Parent weekly report: the circle reads 9 "Assignment submissions", while the summary below reads "completed 0 teacher-assigned exercises. Out of 9 assignments due this week, 0 were submitted on time." | Parent weekly report | Seen | Medium |
| Parent view labelled "Last 30 days" shows 1.543,81 total study hours, more than the 720 hours in 30 days. Probably an all-time figure under a 30-day label. | Parent child performance | Seen | Medium |
| Writing record listed as 7.5, report header shows SCORE: 8, body says 7.5/10. | Writing list, writing report | Seen | Low |
| Number formats differ: comma decimals in the English UI ("9,98 Hours", "54,53%", "1.543,81") and durations written out elsewhere ("2 months, 2 days, 5 hours, 6 minutes"). | Students tab, parent view, class student report | Seen | Low |
| Issue | Where in code | Basis | Level |
|---|---|---|---|
"New feature" notifications navigate to RECAP_2023, a route that is not registered. | notification/screens/NotificationList.tsx:222-223 | Code | Medium |
| Parent menu links to the teacher notification screen. | parent/ParentMenuScreen.tsx:185 | Code | Medium |
| Sign-up always leads to teacher onboarding, even when Parent was selected. | register/index.tsx | Code | Check |
Links that open the app (universal link flyer.dynalinks.app, scheme flyer-partner://) are configured, but no screen handles them. Only push links to /test-result are mapped. | navigator/configNavigator.ts | Code | Medium |
| Push messages that arrive while the app is open are probably not shown (no foreground display library). | provider/NotificationProvider.tsx | Code, uncertain | Check |
| 12 routes are registered but never opened: 10 retired filter screens, the AI hub and an older dashboard report. | navigator/listNavigator.ts | Code | Low |
| "Assign test" picker, resource "All Tests": the first two items are Korean-language lessons tagged Pre A1, followed by phonics items coded JP305 and JP306. | Assign step 1 | Seen; why these rank first is unclear | Check |
| Issue | Basis |
|---|---|
| Some labels are hard-coded in English and do not translate ("Speaking AI", "Writing AI", "Premium/Free", "Hi,"). Default language is English on first launch although the fallback language is Vietnamese. | Code |
| Vietnamese store display name has a trailing space ("Trợ Giảng AI "). Photo-library permission text reads "Flyer need photo library use for upload your profile". | Code |
| Help Center is a phone call; Report a bug opens email. No in-app bug report. | Code (buttons seen) |
| Framework | React Native 0.81.4 · React 19.1 · Expo 54 (bare, with ios/ and android/) · Hermes · New Architecture on |
| Language | TypeScript 5.5, strict · ESLint (airbnb, unicorn, cspell) with zero warnings allowed · Husky pre-commit lint + type-check |
| State and data | Jotai · Apollo Client (GraphQL) · TanStack Query (REST) |
| Navigation | React Navigation 7: one root native stack (83 routes) + 5 bottom tabs |
| UI | Own components (96 files), action sheets, toasts, ECharts and SVG charts, Lottie, OpenSans |
| Languages | English, Vietnamese (i18next, ~1,280 strings each) |
| Size | 357 source files, ~54,600 lines; largest areas: assign test 6.5k, AI tools 6.1k, parent 4.7k, dashboard 3.5k lines |
| Package manager | Yarn 4.12 (the Android workflow pins 4.7.0) |
| Layer | Detail |
|---|---|
| GraphQL | /v2/graphql over HTTP, WebSocket for 1 subscription (single-session sign-out). 63 queries, 44 mutations defined; 58 and 36 used. Hasura endpoint removed on 14/10/2026 (#66). |
| REST v3 | Hooks generated from the OpenAPI spec: 5 of ~270 used (school list; parent weekly report and tuition). The total follows the live staging spec, downloaded on every generation. |
| Headers | x-session-token, device MOBILE_TEACHER or MOBILE_PARENT, device info JSON. REST calls send the token only. |
| Environment | isDev = false is committed, so local builds use production. CI rewrites the line per build (scripts/set-is-dev.js), but runs GraphQL codegen before that step, so development builds are generated from the production schema. |
| Hosts | Production api.flyer.us, Firebase mover-online-english · development staging-api.flyer.us, Firebase flyer-english-staging |
| Service | State |
|---|---|
| Firebase Auth (Google, Apple, phone) | Active |
| Firebase Messaging (push) | Active topics allDevices, teacherApp / parentApp, plus dev in development builds |
| Remote Config | Active 2 live keys (maintenance, minimum version), 2 unused |
| Crashlytics | Active crash capture on by default; the only custom logging is GraphQL errors. No iOS symbol upload step found. |
| Firebase Analytics | Linked, unused 0 custom events. See /tracking-events. |
| Camera, image picker, audio | Active vision-camera, image-picker, expo-av (deprecated in Expo 54) |
| CodePush, AppsFlyer, expo-updates | Dead code commented out or package removed; config left behind. No over-the-air updates. |
| Item | Detail |
|---|---|
| CI on pull requests | Gitea Actions: install, codegen, lint, type-check. No tests, no build. |
| iOS release | Manual workflow: fastlane builds the IPA → Firebase App Distribution (development) or TestFlight (production). Added 05–06/10/2026. |
| Android release | Manual workflow: APK → Firebase App Distribution (development, since 06/2025), or AAB → Play Store internal track (production, added 12/10/2026). |
| Versioning | version.config.json shared by both pipelines (1.7.3, Android code 58). The Xcode project still says 1.7.2, so local builds show "1.7.2 (1)". |
| Bundle id | com.flyer.partner for every environment: staging and production cannot sit on the same phone. |
| Branches | dev is the real trunk; main last updated 08/2024. |
| Activity 2026 | 62 commits (two engineers wrote 61). By month: Jan 22 · Feb 1 · Mar 4 · Apr–Jun 0 · Jul 1 · Aug 17 · Sep 3 · Oct 1–14: 14. 8 of the last 10 pull requests are CI/build work. |
| Risk | Level |
|---|---|
| Android release keystore and its password are committed to the repository. | High |
| Session token stored in plain AsyncStorage, not Keychain/Keystore. Apollo developer tools are enabled in production builds. | Medium |
| Local and debug builds write to production data by default. | Medium |
| One test file, and it is broken; CI never runs tests. | Medium |
| No product events: feature adoption on the app cannot be measured. | Medium |
OpenAPI generator downloads the spec from staging-api.flyer.vn while the app calls .flyer.us. | Low |
Local build steps for the iOS Simulator (pod install, codegen, Xcode 26.4 workaround now merged in #62) were verified on 15/10/2026 and are kept by the product team; the repository README does not cover them.