|
Hi everyone,
List not updated after adding a new item
struct HistoryIView: View {
@StateObject var historyData1 = historyData()
private var totalAmount: Double {
historyData1.item.reduce(0.0) { partialResult, item in
partialResult + item.price
// also can be expressed as { $0 + $1.amount }
}
}
var body: some View {
NavigationView {
List {
Section(header: Text("Invoice History \(totalAmount.formatted(.currency(code: Locale.current.currency?.identifier ?? "BD")))")) {
ForEach(historyData1.item, id: \.id) { it in
HStack {
VStack(alignment: .leading) {
Text(it.cus)
Text(it.cusNum)
Text(it.dat.formatted(date: .abbreviated, time: .shortened))
.foregroundColor(Color("grayed"))
}
Spacer()
VStack {
HStack {
Text("Recipt#:")
.foregroundColor(.red)
Text("\(it.invNum)")
}
Text(it.price, format: .currency(code: Locale.current.currency?.identifier ?? "BD"))
.foregroundColor(.green)
}
}
}
.onDelete(perform: removeItem)
}
}
.navigationTitle("Invoice history")
.navigationBarTitleDisplayMode(.inline)
.toolbar {
ToolbarItem(placement: .navigationBarLeading) {
Button("Delete All") {
historyData1.item.removeAll()
}
.tint(.red)
}
}
}
}
func removeItem(at offsets: IndexSet) {
itemsData.items.remove(atOffsets: offsets)
}
}
How to fix that?
Thanks in Advance
|
|
Hi there! Where and how do you add item here? In your struct you have only option for delete...
|
|
Hi @ygeras , add from invoiceView :
Button("Save") {
let item = HistoryData(storN: storeName, storNum: contactNumber, invNum: invoiceNumber, dat: invoiceDate, cus: customerName, cusAddr: customerAddress, cusNum: cusContactNumber, price: totalAmount)
historyData.item.insert(item, at: 0)
}
this is model :
struct HistoryData: Identifiable, Codable {
var id = UUID()
let storN: String
let storNum: String
let invNum: String
let dat: Date
let cus: String
let cusAddr: String
let cusNum: String
let price: Double
}
class historyData: ObservableObject {
@Published var item: [HistoryData] = [] {
// FOR STORE DATA IN THE UserDefaults.
didSet {
let encoder = JSONEncoder()
if let encode = try? encoder.encode(item) {
UserDefaults.standard.set(encode, forKey: "HistoryData")
}
}
}
// FOR LOAD DATA FROM UserDefaults.
init() {
if let savedItems = UserDefaults.standard.data(forKey: "HistoryData") {
if let decodedItems = try? JSONDecoder().decode([HistoryData].self, from: savedItems) {
item = decodedItems
return
}
}
item = []
}
}
|
|
pls share your invoiceView.
|
|
InvoiceView:
struct InvoiceView: View {
// class.
@StateObject var itemsData = ItemsData()
@AppStorage("storeName") private var storeName = ""
@AppStorage("invoiceNumber") private var invoiceNumber = ""
@AppStorage("contactNumber") private var contactNumber = ""
@State private var invoiceDate = Date()
@AppStorage("customerName") private var customerName = ""
@AppStorage("customerAddress") private var customerAddress = ""
@AppStorage("cusContactNumber") private var cusContactNumber = ""
@State private var showingAddItem = false
@State private var showingHistoryView = false
// FOR IMAGE PICKER.
@State private var selectedItem: PhotosPickerItem? = nil
@State private var selectedImageData: Data? = nil
// FOR CALCULATE TOTAL AMOUNT.
private var totalAmount: Double {
itemsData.items.reduce(0.0) { partialResult, item in
partialResult + item.price
// also can be expressed as { $0 + $1.amount }
}
}
// FOR CALCULATE DISCOUNT AMOUNT. (READING FROM AddView)
private var discountAmount: Double {
itemsData.items.reduce(0.0) { partialResult, item in
partialResult + item.discountAmount
// also can be expressed as { $0 + $1.amount }
}
}
// FOR CALCULATE VAT AMOUNT.
private var vatAmount1: Double {
itemsData.items.reduce(0.0) { partialResult, item in
if item.vat > 0 {
let netAmount = item.price / (1 + item.vat/100)
let vatamount = item.price - netAmount
return partialResult + vatamount
}
return partialResult
}
}
@State private var paymentM = "Cash"
let paymentsList = ["Cash", "BenefitPay", "Debit Card"]
@ObservedObject var historyData: historyData
// @ObservedObject var totalPrice: TotalPrices
@State private var type = "Income"
@ObservedObject var expenses: Expenses
var body: some View {
NavigationView {
List {
// FOR IMAGE PICKER.
PhotosPicker(
selection: $selectedItem,
matching: .images,
photoLibrary: .shared()) {
Text("Select a logo")
}
.onChange(of: selectedItem) { newItem in
Task {
// Retrieve selected asset in the form of Data
if let data = try? await newItem?.loadTransferable(type: Data.self) {
selectedImageData = data
}
}
}
Group {
Section {
if let selectedImageData,
let uiImage = UIImage(data: selectedImageData) {
Image(uiImage: uiImage)
.resizable()
.aspectRatio(contentMode: .fit)
.scaledToFit()
.frame(width: 200, height: 200)
.cornerRadius(200)
}
}
}
Section(header: Text("Store Details")) {
TextField("Store Name", text: $storeName)
TextField("Invoice number", text: $invoiceNumber)
TextField("contact number", text: $contactNumber)
}
Section{
DatePicker("Date", selection: $invoiceDate)
}
Section(header: Text("Customer Details")) {
TextField("Customer Name", text: $customerName)
TextField("Customer Address", text: $customerAddress)
TextField("contact number", text: $cusContactNumber)
}
Group {
// Add Item button
// Section {
Button{
showingAddItem = true
} label: {
HStack {
Image(systemName: "plus")
Text("Add Item")
}
}
.sheet(isPresented: $showingAddItem) {
AddView(ItemsData: itemsData)
}
// }
ForEach(itemsData.items, id: \.id) { item in
HStack {
VStack(alignment: .leading) {
Text(item.name)
.lineLimit(3)
Text("x\(item.quantity.formatted())")
.foregroundColor(Color("grayed"))
}
Spacer()
VStack {
Text(item.price, format: .currency(code: Locale.current.currency?.identifier ?? "BD"))
.lineLimit(3)
}
}
}
.onDelete(perform: removeItem)
}
HStack {
Text("Discount amount")
Spacer()
Text("\(discountAmount.formatted(.currency(code: Locale.current.currency?.identifier ?? "BD")))")
.foregroundColor(.blue)
}
HStack {
Text("VAT amount")
Spacer()
Text("\(vatAmount1.formatted(.currency(code: Locale.current.currency?.identifier ?? "BD")))")
.foregroundColor(.red)
}
HStack {
VStack(alignment: .leading) {
Text("Total")
Text(vatAmount1 > 0 ? "inc. VAT" : "")
.foregroundColor(Color("grayed"))
}
Spacer()
Text("\(totalAmount.formatted(.currency(code: Locale.current.currency?.identifier ?? "BD")))")
.foregroundColor(.green)
}
Group {
Section {
Picker("payment method", selection: $paymentM) {
ForEach(paymentsList, id: \.self) {
Text($0)
}
}
}
}
// ShareLink("Export PDF", item: render())
}
.navigationTitle("Invoice Maker")
.navigationBarTitleDisplayMode(.inline)
.toolbar {
ToolbarItemGroup {
ShareLink("Export PDF", item: render())
Button("Save") {
let income = ExpenseItem(name: customerName, type: type, amount: totalAmount - vatAmount1, date: invoiceDate, vat: vatAmount1)
expenses.items.insert(income, at: 0)
let item = HistoryData(storN: storeName, storNum: contactNumber, invNum: invoiceNumber, dat: invoiceDate, cus: customerName, cusAddr: customerAddress, cusNum: cusContactNumber, price: totalAmount)
historyData.item.insert(item, at: 0)
// showingHistoryView = true
}
// .sheet(isPresented: $showingHistoryView) {
// HistoryIView()
// }
}
ToolbarItem(placement: .navigationBarLeading) {
Button("Clear") {
itemsData.items.removeAll(keepingCapacity: true)
customerName = ""
customerAddress = ""
cusContactNumber = ""
}
.tint(.red)
}
}
}
}
func removeItem(at offsets: IndexSet) {
itemsData.items.remove(atOffsets: offsets)
}
|
|
Sorry @mahoozi97 :) looks a bit messy, not sure why you need all those @AppStorages. If you share full project via github maybe i can have a look at where might be the issue. But can say for sure that item is inserted just fine. I cannot play with your code as many aspects of it are missing. But if you have a look at the below code and maybe copy/paste to have a look it works just fine. Maybe the issue with passing the data to Invoice View
struct HistoryIView: View {
@StateObject var historyData1 = DataModel()
var body: some View {
NavigationView {
List {
Section(header: Text("Invoice History \(historyData1.totalAmountView)")) {
ForEach(historyData1.items) { it in
HStack(alignment: .top) {
VStack(alignment: .leading) {
Text(it.cus)
Text(it.cusNum)
Text(it.dat.formatted(date: .abbreviated, time: .shortened))
.font(.footnote)
.foregroundStyle(.secondary)
}
Spacer()
VStack(alignment: .trailing) {
HStack {
Text("Recipt#:")
.foregroundColor(.red)
Text("\(it.invNum)")
}
Text(it.price, format: .currency(code: Locale.current.currency?.identifier ?? "BD"))
.foregroundColor(.green)
}
}
}
.onDelete(perform: removeItem)
}
}
.navigationTitle("Invoice history")
.navigationBarTitleDisplayMode(.inline)
.toolbar {
ToolbarItem(placement: .navigationBarLeading) {
Button("Delete All") {
historyData1.items.removeAll()
}
.tint(.red)
}
ToolbarItem(placement: .navigationBarTrailing) {
Button {
let newItem = HistoryData(storN: "Test", storNum: "Test", invNum: "Test", dat: .now, cus: "Text", cusAddr: "Text", cusNum: "Text", price: 10000)
historyData1.items.insert(newItem, at: 0)
} label: {
Image(systemName: "plus")
}
}
}
}
}
func removeItem(at offsets: IndexSet) {
historyData1.items.remove(atOffsets: offsets)
}
}
struct HistoryData: Identifiable, Codable {
var id = UUID()
let storN: String
let storNum: String
let invNum: String
let dat: Date
let cus: String
let cusAddr: String
let cusNum: String
let price: Double
}
class DataModel: ObservableObject {
@Published var items: [HistoryData] = [] {
// FOR STORE DATA IN THE UserDefaults.
didSet {
let encoder = JSONEncoder()
if let encode = try? encoder.encode(items) {
UserDefaults.standard.set(encode, forKey: "HistoryData")
}
}
}
// FOR LOAD DATA FROM UserDefaults.
init() {
// if let savedItems = UserDefaults.standard.data(forKey: "HistoryData") {
// if let decodedItems = try? JSONDecoder().decode([HistoryData].self, from: savedItems) {
// items = decodedItems
// return
// }
// }
items = {
var items = [HistoryData]()
for number in 1...100 {
let item = HistoryData(storN: "StoreN \(number)",
storNum: "StoreNum \(number)",
invNum: "InvNum \(number)",
dat: .now,
cus: "Customer \(number)",
cusAddr: "Address \(number)",
cusNum: "Cus \(number)",
price: 100
)
items.append(item)
}
return items
}()
}
var totalAmount: Double {
items.reduce(0.0) { $0 + $1.price }
}
var totalAmountView: String {
totalAmount.formatted(.currency(code: Locale.current.currency?.identifier ?? "BD"))
}
}
|