Skip to content

cywuuuu/TexBookSub

Repository files navigation

TexBookSub Beihang University Textbook Subscription App

[TOC]

preview

simulator_screenshot_E9420DEE-BE67-487D-85D2-F7D3D1017082 Simulator Screen Shot - iPhone 11 - 2022-11-10 at 22.10.48 Simulator Screen Shot - iPhone 11 - 2022-11-10 at 22.11.07
Simulator Screen Shot - iPhone 11 - 2022-11-10 at 22.14.41 Simulator Screen Shot - iPhone 11 - 2022-11-10 at 22.12.33 Simulator Screen Shot - iPhone 11 - 2022-11-10 at 22.15.15
Simulator Screen Shot - iPhone 11 - 2022-11-10 at 22.18.24 Simulator Screen Shot - iPhone 11 - 2022-11-10 at 22.17.54 Simulator Screen Shot - iPhone 11 - 2022-11-10 at 22.17.25

description

Every semester, textbook ordering becomes a tedious task that every student has to put effort into. Either each small group collects and summarizes the book purchasing information, which is then submitted by the group leader to the textbook office for ordering and distribution at the class level. Or students purchase recommended textbooks only to find out they are not needed for the entire semester. Alternatively, students try to contact senior students to buy second-hand books but often struggle to find available sellers or miss out on information shared in large group chats. It is evident that purchasing textbooks at the beginning of the semester is a highly cumbersome and scattered process. This inspires us to establish a non-profit platform within the university to centralize the channels for purchasing textbooks from the textbook office and buying/selling second-hand textbooks among students, all done online.

By doing so, it would be convenient for the textbook office as they no longer have to coordinate with each small group, and it would be easier for the small group representatives who would no longer need to handle textbook ordering, collecting payments, and book distribution. On the other hand, it would also eliminate the inconvenience caused by information asymmetry for students buying and selling textbooks.

arch

image-20221110224852571

This project adopts the "SwiftUI + MVVM" (pseudo) pattern. In the "Model" layer, two entities, "user" and "book", are established. In the "ViewModel" layer, to save effort, the ViewModel for each view is integrated into a single class. This class is accessed and shared through a singleton pattern in each "View" page. The ViewModel is marked with @MainActor to ensure that when a @Published variable changes, all the pages are updated accordingly.

@MainActor class ViewModel : ObservableObject{

    static let vm = ViewModel()
    @Published var publishedPool:[BookModel]
    @Published var userPool: [UserModel]
    @Published var nowUser: UserModel?
    @Published var displayMode: SearchTypes = SearchTypes.all
    @Published var searchKey: String = ""

Some components are written in the component section, and they use @State and @Binding for value binding. However, due to the singleton pattern of the ViewModel, it may cause slow page refreshing and needs further improvement. Additionally, if persistence is required, this approach can be used for reading and writing JSON. However, due to time constraints, I haven't implemented Codable for User and Book yet. There is room for further improvement.

    
   func savePublishPool() {
       do {
           let data1 = try JSONEncoder().encode(publishedPool)
           try data1.write(to: savePublishedPoolPath, options: [.atomic, .completeFileProtection])
       } catch {
           print("Unable to save data.")
       }
   }

   func saveUser() {
       do {
           let data1 = try JSONEncoder().encode(userPool)
           try data1.write(to: saveUserPoolPath, options: [.atomic, .completeFileProtection])
           let data2 = try JSONEncoder().encode(nowUser)
           try data2.write(to: saveNowUserPath, options: [.atomic, .completeFileProtection])
       } catch {
           print("Unable to save data.")
       }
   }

In the View layer, the structure is as follows:

image-20221110230449238

function design

  1. Login and Registration In the ViewModel, the current user is recorded as nowUser, and the UserPool keeps track of registered users. The logic for login and registration is as follows:
    func makeregister(username: String, password: String) -> Bool{
        if (userPool.contains(where: {$0.username == username})) {
            return false
        } else {
            userPool.append(UserModel(username: username, password: password, cart: [:], published: []))
//            saveUser()
            return true
        }
    }
    
    func login(username: String, password: String) -> (Bool, String){
        if let user = userPool.first(where: {$0.username == username}) {
           // do something with foo
            if user.password == password {
                nowUser = user
                return (true, "Login Succeeded")
            } else {
                return (false, "Password mismatched")
            }
        } else {
           // item could not be found
            return (false, "Username Not Found \nPlease Register First")
        }
    }
Simulator Screen Shot - iPhone 11 - 2022-11-10 at 22.10.48Simulator Screen Shot - iPhone 11 - 2022-11-10 at 22.10.03Simulator Screen Shot - iPhone 11 - 2022-11-10 at 22.09.47
  1. Publishing and Managing Textbooks

The code for publishing and managing textbooks is located in CheckOut.swift within the PublishView. This functionality allows users to upload and publish new textbooks. In the view, we can create a new Book object using the parameters obtained from the bindings and then call the corresponding method in the ViewModel.

The ViewModel implementation for this functionality would include:

    func publishBookToPool(Bk:BookModel) {
        publishedPool.append(Bk)
//        savePublishPool() 如需持久化则加入这个
    }

Simulator Screen Shot - iPhone 11 - 2022-11-10 at 22.17.54Simulator Screen Shot - iPhone 11 - 2022-11-10 at 22.17.25

截屏2022-11-10 22.18.14截屏2022-11-10 22.18.05

book management

image-20221110231630769

    func deletePublish(Bk:BookModel) {
        publishedPool = publishedPool.filter { $0 !== Bk }
//        savePublishPool()
    }
//计算属性获取当前用户的发布
var nowUserPublish: [BookModel] {
        get {
            return publishedPool.filter{$0.publisher == nowUser?.username}
        }
    }
  1. Purchasing Textbooks

Each User maintains a Cart as a dictionary of [Book: Int] to keep track of the currently purchased items and their quantities.

    func buyBook(bk: BookModel, amount: Int) {
        print("buy book", bk, amount)
        nowUser?.addCart(bk: bk, num: amount)
//        saveUser()
    }

    func addCart(bk: BookModel, num: Int) {
        if cart[bk] != nil {
            cart[bk]! += num
            print(cart)
        } else {
            cart[bk] = num
            print(cart)
        }
    }

Effect:

Simulator Screen Shot - iPhone 11 - 2022-11-10 at 22.12.44

Initial shopping cart.

image-20221110233026904

Buying two books of Verilog.

Simulator Screen Shot - iPhone 11 - 2022-11-10 at 22.18.24

Shopping cart after purchase.

Additionally, the information on our shopping homepage is obtained through computed properties.

var trending: [BookModel] {
        get {
            return publishedPool.filter{
                $0.recommend
            }
        }
    }
    

    @Published var searchRes: [BookModel]
    func getSearchRes() {
            switch displayMode {
            case .course:
                searchRes = publishedPool.filter({ $0.courses.hasPrefix(searchKey)})
            case .college:
                searchRes = publishedPool.filter({ $0.college.hasPrefix(searchKey)})
            case .bookName:
                searchRes = publishedPool.filter({ $0.title.hasPrefix(searchKey)})
            case .publisher:
                searchRes =  publishedPool.filter({ $0.publisher.hasPrefix(searchKey)})
            case .all:
                searchRes = publishedPool
            }
        
    }

Simulator Screen Shot - iPhone 11 - 2022-11-10 at 22.11.07

  1. clear shopping cart

image-20221110233127216

About

swiftui, buaa 2022, big homework

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages