Using Delegates - Have Customer and Employee Controllers Appear when Uploading to Firestore

42 Views Asked by At

What I'm trying to do is when customers submit a job request, which is the RequestJobConfirmationController, I want to be able to pull up the FindEmployeeJobRequestController on the customer side and CustomerJobRequestController on the employee's side when the customer is searching for an employee. Right now, I'm having trouble bringing up CustomerJobRequestController when I reach the FindEmployeeJobRequestController on the customer side. Also, I need to pull up the CustomerJobRequestController when the jobRequest businessId matches employees' businessId, and then have the employee's statusAvailability set to true, and then send the jobRequest to the first position's employee. Let me know if you need more details of what I need, thank you!

Service

// MARK: - CustomerService

struct CustomerService {

    static func uploadCustomerAndJobRequest(jobDetails: JobDetailCredentials, completion: CollectionCompletion) {
        
        guard let uid = Auth.auth().currentUser?.uid else { return }
        
        let values = ["fullname" : jobDetails.fullname,
                      "username" : jobDetails.username,
                      "businessName" : jobDetails.businessName,
                      "businessId" : jobDetails.businessId,
                      "address" : jobDetails.address,
                      "firstDateAndTimes" : jobDetails.firstDateAndTimes,
                      "secondDateAndTimes" : jobDetails.secondDateAndTimes,
                      "thirdDateAndTimes" : jobDetails.thirdDateAndTimes,
                      "timeConstraints" : jobDetails.timeConstraints,
                      "jobDescription" : jobDetails.jobDescription,
                      "timestamp" : Timestamp(date: Date())] as [String : Any]
        
        
        REF_JOB_REQUEST_DETAILS.document(uid).collection("job-request-details").addDocument(data: values, completion: completion)
    }

    static func observeCurrentCustomerJobRequest(completion: @escaping(JobRequest) -> Void) {
        guard let uid = Auth.auth().currentUser?.uid else { return }
        
        REF_JOB_REQUEST_DETAILS.document(uid).collection("job-request-details").order(by: "timestamp").addSnapshotListener { snapshot, error in
            snapshot?.documentChanges.forEach({ change in
                let dictionary = change.document.data()
                let jobRequest = JobRequest(customerUid: uid, dictionary: dictionary)
                completion(jobRequest)
            })
        }
    }
    
    static func fetchCustomerJobRequest(uid: String, completion: @escaping(JobRequest) -> Void) {
        // 'Confirm Job' called once user taps button.
        guard let uid = Auth.auth().currentUser?.uid else { return }
        
        let query = REF_JOB_REQUEST_DETAILS.document(uid).collection("job-request-details").order(by: "timestamp")
        
        query.addSnapshotListener { snapshot, error in
            snapshot?.documentChanges.forEach({ change in
                let dictionary = change.document.data()
                let jobRequest = JobRequest(customerUid: uid, dictionary: dictionary)
                completion(jobRequest)
            })
        }
        
    }
    
    static func fetchEmployeesForJobRequest(completion: @escaping ([Employee]) -> Void) {
        
        guard let uid = Auth.auth().currentUser?.uid else { return }
        
        let query = REF_JOB_REQUEST_DETAILS.document(uid).collection("job-request-details").order(by: "timestamp")
        
        query.addSnapshotListener { snapshot, error in
            if let error = error {
                print("Error fetching job request document: \(error.localizedDescription)")
                completion([])
                return
            }
            
            guard let documents = snapshot?.documents, !documents.isEmpty else {
                print("No job request document found")
                completion([])
                return
            }
            
            let jobRequestData = documents[0].data()
            guard let businessId = jobRequestData["businessId"] as? String else {
                print("Business ID not found in job request document")
                completion([])
                return
            }
            
            REF_EMPLOYEES.whereField("businessId", isEqualTo: businessId)
                .whereField("statusAvailability", isEqualTo: true)
                .getDocuments { snapshot, error in
                    if let error = error {
                        print("Error fetching employees: \(error.localizedDescription)")
                        completion([])
                        return
                    }
                    
                    var employees = [Employee]()
                    for document in snapshot?.documents ?? [] {
                        let data = document.data()
                        let employee = Employee(dictionary: data)
                        employees.append(employee)
                    }
                    completion(employees)
                }
        }
        
    }

}

RequestJobConfirmationController

class RequestJobConfirmationController: UIViewController {

    // MARK: - Properties
    
    var findEmployeeController: FindEmployeeJobRequestController!

    // MARK: - Selectors

    @objc func handleConfirm() {
        
        let jobDetails = JobDetailCredentials(fullname: fullname, username: username, businessName: businessName, businessId: selectedCompanyID,
                                              address: address, firstDateAndTimes: firstDateAndTimes, secondDateAndTimes: secondDateAndTimes,
                                              thirdDateAndTimes: thirdDateAndTimes, timeConstraints: timeConstraints,
                                              jobDescription: jobDescription)
        
        CustomerService.uploadCustomerAndJobRequest(jobDetails: jobDetails) { error in
            if let _ = error {
                self.simpleAlert(title: "Error", msg: "Unable to upload job details, please try again later.")
                return
            }
            
            let controller = FindEmployeeJobRequestController()
            controller.delegate = self
            self.findEmployeeController = controller
            controller.modalPresentationStyle = .fullScreen
            self.present(controller, animated: true, completion: nil)
        }
        
    }

}

// MARK: - FindEmployeeJobRequestDelegate

extension RequestJobConfirmationController: FindEmployeeJobRequestDelegate  {
    
    func didConfirmJobRequest() {
        guard let jobRequest = self.jobRequest else { return }
        let controller = CustomerJobRequestController(jobRequest: jobRequest)
        present(controller, animated: true)
    }
    
}

FindEmployeeJobRequestController

protocol FindEmployeeJobRequestDelegate: AnyObject {
    func didConfirmJobRequest()
}

class FindEmployeeJobRequestController: UIViewController {
    
    // MARK: - Properties
    
    weak var delegate: FindEmployeeJobRequestDelegate?

    // MARK: - Lifecycle
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        fetchCustomerJobRequest()
        fetchEmployeesForJobRequest()
    }
    
    // MARK: - API
    
    func fetchCustomerJobRequest() {
        guard let uid = Auth.auth().currentUser?.uid else { return }
        CustomerService.fetchCustomerJobRequest(uid: uid) { jobRequest in
            self.jobRequest = jobRequest
        }
    }
    
    func fetchEmployeesForJobRequest() {
        CustomerService.fetchEmployeesForJobRequest { employees in
            self.employees = employees
            print("DEBUG: Employee array \(employees)")
        }
    }
    
    func confirmJobRequest() {
        delegate?.didConfirmJobRequest()
    }

}

CustomerJobRequestController

class CustomerJobRequestController: UIViewController, FindEmployeeJobRequestDelegate {

    // MARK: - Properties
    
    let jobRequest: JobRequest
    
    var availableEmployees: [Employee] = []
    var lastSelectedEmployeeIndex = 0

    // MARK: - Lifecycle
    
    init(jobRequest: JobRequest) {
        self.jobRequest = jobRequest
        super.init(nibName: nil, bundle: nil)
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
    }
    
    // MARK: - API

    // MARK: - Helper Functions

    func filterAvailableEmployees() -> [Employee] {
        let filteredEmployees = availableEmployees.filter { $0.position == 1 && $0.statusAvailability == true }
        return filteredEmployees
    }
    
    func getNextAvailableEmployee() -> Employee? {
        let filteredEmployees = filterAvailableEmployees()
        
        guard !filteredEmployees.isEmpty else {
            return nil
        }

        let nextEmployee = filteredEmployees[lastSelectedEmployeeIndex]
        lastSelectedEmployeeIndex = (lastSelectedEmployeeIndex + 1) % filteredEmployees.count
        return nextEmployee
    }
    
    func initiateJobRequest() {
        if let nextEmployee = getNextAvailableEmployee() {
            let jobRequestData = prepareJobRequest(employee: nextEmployee)
            let jobRequest = JobRequest(customerUid: "", dictionary: jobRequestData)
            let controller = CustomerJobRequestController(jobRequest: jobRequest)
            present(controller, animated: true, completion: nil)
        } else {
            print("No available employees.")
        }
    }
    
    func prepareJobRequest(employee: Employee) -> [String : Any] {
        var jobRequestData: [String : Any] = [:]
        
        jobRequestData["employeeUid"] = employee.uid
        jobRequestData["customerUid"] = jobRequest.customerUid
        jobRequestData["fullname"] = jobRequest.fullname
        jobRequestData["username"] = jobRequest.username
        jobRequestData["businessName"] = jobRequest.businessName
        jobRequestData["businessId"] = jobRequest.businessId
        jobRequestData["address"] = jobRequest.address
        jobRequestData["firstDateAndTimes"] = jobRequest.firstDateAndTimes
        jobRequestData["secondDateAndTimes"] = jobRequest.secondDateAndTimes
        jobRequestData["thirdDateAndTimes"] = jobRequest.thirdDateAndTimes
        jobRequestData["timeConstraints"] = jobRequest.timeConstraints
        jobRequestData["jobDescription"] = jobRequest.jobDescription
        jobRequestData["timestamp"] = jobRequest.timestamp
        jobRequestData["state"] = jobRequest.state
        
        return jobRequestData
    }
    
    func didSelectEmployee() {
        if let nextEmployee = getNextAvailableEmployee() {
            print("Selected Employee: \(nextEmployee.fullname)")
            initiateJobRequest()
        } else {
            simpleAlert(title: "Error", msg: "No available employees match the criteria.")
        }
    }
    
    func didConfirmJobRequest() {
        initiateJobRequest()
    }

}
0

There are 0 best solutions below