Here is the remaining code and questions :
why do you use string ( or maybe I change in between and I ws the one using String at first ^^sorry if yes haha
are you trying to use @binding here to clear all the button to false regardless of the project and it;s the only way to achieve it ?
this 2 line of code timesheetCalculation.checkRemainingHours(isSet: true) keep telling me that it will never be used but actually it's beeing use and working : warning from Apple is Result of call to 'checkRemainingHours(isSet:)' is unused
timesheetCalculation.checkRemainingHours(isSet: true)
//
// HourButton.swift
// MyPmV1
//
// Created by Sebastien BENAVIDES on 9/2/24.
//
import SwiftUI
struct HourButton: View,Identifiable, Observable { //This Identifiable is
@Environment(TimesheetCalculation.self) var timesheetCalculation
//MARK: - Variable & Constants
var id: Int = 1001 //CLAUDE USE STRING
@State var isSet: Bool
// CLAUDE IUSE BINDING @Binding var isSet: Bool // A Binding, as we change the value and want it updated in TimeKeyInRow
var value: Float
//MARK: - Body
var body: some View {
@State var timesheetCalculation = timesheetCalculation
HStack {
Button {
if value <= timesheetCalculation.remainingHour || isSet == true {
isSet.toggle()
print("clic on Project : \(id) an turn to : \(isSet) for \(value)h")
if isSet == true {
timesheetCalculation.hourchoosen = value
timesheetCalculation.checkRemainingHours(isSet: true)
timesheetCalculation.hourchoosen = value
timesheetCalculation.cvsrecordedtrackingcodek(idofthiskeyin: id, valueOfThisKeyin: value, itemsisSet: isSet)
} else {
timesheetCalculation.hourchoosen = value
timesheetCalculation.checkRemainingHours(isSet: false)
timesheetCalculation.cvsrecordedtrackingcodek(idofthiskeyin: id, valueOfThisKeyin: value, itemsisSet: isSet)
}
} else {
// Warning message
print("Please understand that you cannot work more than 8h")
}
} label: {
Label("" , systemImage: isSet ? "circle.fill" : "circle")
.labelStyle(.iconOnly)
.foregroundStyle(isSet ? .blue : .gray)
}.id(id)
}
}
}
//MARK: - Preview
struct HourButton_Previews: PreviewProvider {
static var previews: some View {
//#Preview {
let timesheetCalculation = TimesheetCalculation()
HourButton(id: 1001, isSet: false, value: 3).environment(timesheetCalculation)
}
}
//MARK: - Extension
extension Array where Element: Equatable {
mutating func removeFirstOccurrence(of element: Element) {
if let index = firstIndex(of: element) {
remove(at: index)
}
}
}
here is the logic code
//
// TimesheetCalculation.swift
// MyPmV1
//
// Created by Sebastien BENAVIDES on 12/2/24.
//
import Foundation
import SwiftUI
@Observable
class TimesheetCalculation {
var date = Date()
let dateRange: ClosedRange<Date> = {
let calendar = Calendar.current
let startComponents = DateComponents(year: 2024, month: 1, day: 1)
let endComponents = DateComponents(year: 2024, month: 12, day: 31)
return calendar.date(from:startComponents)!
...
calendar.date(from:endComponents)!
}()
var isSet: [Bool] = [false, false, false, false, false,false,false,false]
let listOfPossibleHours: [Float] = [0.5,1,2,3,4,8]
let listOfPossibleHoursText: [String] = [".5","1","2","3","4","8"]
var hourchoosen: Float = 0
var remainingHour: Float = 8
var cvsrecordedtrackingcodek: String = ""
var cvsrecordedtrackingcodekall: [String] = []
func checkRemainingHours(isSet: Bool) -> Float {
if isSet == true {
remainingHour = remainingHour - hourchoosen
return remainingHour
} else {
remainingHour = remainingHour + hourchoosen
return remainingHour
}
}
func cvsrecordedtrackingcodek(idofthiskeyin id:Int,valueOfThisKeyin value:Float,itemsisSet isSet:Bool) {
let newstring = String("ProjectID:\(id) Number of Hours: \(value) For Day: \(date.formatted(date: .abbreviated, time: .omitted))")
if isSet == true {
cvsrecordedtrackingcodekall.append(newstring)
} else {
cvsrecordedtrackingcodekall.removeFirstOccurrence(of: newstring)
}
print(cvsrecordedtrackingcodekall)
}
}
here is my Modeldata
//
// ModelData.swift
// MyPmV1
//
// Created by Sebastien BENAVIDES on 3/2/24.
//
import Foundation
import Observation
@Observable
class ModelData {
var projects: [Project] = load("ProjectData.json")
var hikes: [Hike] = load("hikeData.json")
var profile = Profile.default
var isSet: [Bool] = [false, false, false, false, false,false,false,false]
var features: [Project] {
projects.filter { $0.isFeatured }
}
var categories: [String: [Project]] {
Dictionary(
grouping: projects,
by: { $0.category.rawValue }
)
}
var buisness: [String: [Project]] {
Dictionary(
grouping: projects,
by: { $0.buisness_model.rawValue }
)
}
var customers: [String: [Project]] {
Dictionary(
grouping: projects,
by: { $0.customer.rawValue }
)
}
}
func load<T: Decodable>(_ filename: String) -> T {
let data: Data
guard let file = Bundle.main.url(forResource: filename, withExtension: nil)
else {
fatalError("Couldn't find \(filename) in main bundle.")
}
do {
data = try Data(contentsOf: file)
} catch {
fatalError("Couldn't load \(filename) from main bundle:\n\(error)")
}
do {
let decoder = JSONDecoder()
return try decoder.decode(T.self, from: data)
} catch {
fatalError("Couldn't parse \(filename) as \(T.self):\n\(error)")
}
}