diff --git a/README.md b/README.md index 5e7ece5..e8206a5 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,20 @@ # Graduator -Graduator is an iOS application developed with SwiftUI that helps users manage their academic `units`, `subjects`, and grades. Users can add and delete `subjects`, edit the weight and name of `subjects` and `units`, and input grades. The app displays weighted averages and explains the conditions for graduating from the Clermont Auvergne Tech Institute's mobile development BSc in 2023. +* [Features](#features) + - [Persistence](#persistence) + - [Weighted average](#weighted-average) + - [Deleting a `subject`](#deleting-a-subject) + - [Changing a grade](#changing-a-grade) + - [Creating a `subject`](#creating-a-subject) +* [Known limitations and issues](#known-limitations-and-issues) + - [`Unit` and `subject` weight changes cancel with a delay](#unit-and-subject-weight-changes-cancel-with-a-delay) + - [The UI is unintuitive when updating](#the-ui-is-unintuitive-when-updating) + - [Change notifications are not implemented per se](#change-notifications-are-not-implemented-per-se) +* [Architecture](#architecture) + - [Focusing on VMs](#focusing-on-vms) + - [As a whole](#as-a-whole) + +Graduator is an iOS application developed with SwiftUI, that helps users manage their academic `units`, `subjects`, and grades. Users can add and delete `subjects`, edit the weight and name of `subjects` and `units`, and input grades. The app displays weighted averages and explains the conditions for graduating from the Clermont Auvergne Tech Institute's mobile development BSc in 2023. view from the home page view from a unit page @@ -24,7 +38,7 @@ A weighted average means that a `subject` or `unit`'s weight plays a part in cal before changing a subject's weight after changing a subject's weight -### Deleting a `Subject` +### Deleting a `subject` In the app, users can delete a `subject` by swiping it off the list, right-to-left. @@ -43,21 +57,85 @@ After a grade was changed, in order to save the change and to see it reflected i grade changed -### Creating a `Subject` +### Creating a `subject` -Finally, users can create a `subject` when in edit mode. After clicking on *'Modifier'*, look for a `+` in the top navigation bar. +Finally, users can create a `subject` when in edit mode. After clicking on *"Modifier"*, look for a `+` in the top navigation bar. subject deleted creating a subject subject created +## Known limitations and issues + +### `Unit` and `subject` weight changes cancel with a delay + +ℹ️ **There was an issue with `subjects` getting updated even after a user presses *"Annuler"*. That issue was solved in #6** + +See #7 + +When canceling an update to a weight, the value does not instantaneously revert to the old value, like we would expect. + +If a user presses *"Modifier"* again, and then presses *"Annuler"* again, the old value finally comes back. + +We haven't found the source of the issue. The logic is the same as with names, except that simple formatters are involved. +Canceling changes made to names is a feature that works as expected. + +Since the data appears to be eventually consistent, this issue was left unsolved. + +### The UI is unintuitive when updating + +See #4 + +When updating names and weights for `units` and `subjects`, many users would expect to see a `sheet` appear. + +While we did implement that for creating a new `subject`, we did not do it for updates. Instead, the text fields used to +display the data just become editable when the *"Modifier"* button is pressed. + +### Change notifications are not implemented per se + +See #5 and [this course](https://codefirst.iut.uca.fr/documentation/mchSamples_Apple/docusaurus/iOS_MVVM_guide/docs/viewModels/changeNotifications/) + +Instead, "detail" views observe VMs that are higher up in the hierarchy. + +```swift +import SwiftUI + +struct SubjectViewCell: View { + @ObservedObject var subjectVM: SubjectVM + @ObservedObject var unitVM: UnitVM + @ObservedObject var unitsManagerVM: UnitsManagerVM + + @State private var isGradeEditable = false + + var body: some View { + //... +``` + +That way, they can propagate changes by themselves. + +```swift +Toggle("", isOn: $isGradeEditable) + //... + .onChange(of: isGradeEditable) { + //... + subjectVM.onEdited() + unitVM.updateSubject(subjectVM) + try await unitsManagerVM.updateUnit(unitVM) + } //... + +``` + +It's clunky, it's fragile -- but it's working and so, for lack of time, it's staying for the foreseeable future. ## Architecture Graduator is based on the MVVM (Model-View-ViewModel) architectural pattern. The below UML class diagram details -the structure of the models, viewmodels, and views for `UnitsManager`, `Unit`, and `Subject`. Notice how, +the structure of the models, viewmodels, and views for `UnitsManager`, `Unit`, and `Subject`. Notice how, as discussed in [this subpart](#change-notifications-are-not-implemented-per-se), to circumvent [this issue](https://codefirst.iut.uca.fr/documentation/mchSamples_Apple/docusaurus/iOS_MVVM_guide/docs/viewModels/changeNotifications/problematic/), -we insert an entire hierarchy of VMs in certain views, so that they can update all those VMs when a detail gets edited. It's dirty, and it's staying that way for the foreseeable future. +we insert an entire hierarchy of VMs in certain views, so that they can update all those VMs when a detail gets edited. +It's dirty, and it's staying that way for the foreseeable future. + +### Focusing on VMs ```mermaid classDiagram @@ -136,6 +214,7 @@ classDiagram ``` +### As a whole It might be useful to note that, just like `UnitVM`s aggregate `SubjectVM`s, `Unit`s aggregate `Subject`s, but these relationship between `Model` entities were removed from the diagram above for clarity.