Skip to content

Commit

Permalink
Implement activity logs
Browse files Browse the repository at this point in the history
  • Loading branch information
cp-amisha-i committed Nov 22, 2024
1 parent d2fd817 commit ce8c6f8
Show file tree
Hide file tree
Showing 121 changed files with 3,725 additions and 1,210 deletions.
2 changes: 1 addition & 1 deletion .firebaserc
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,4 @@
}
},
"dataconnectEmulatorConfig": {}
}
}
4 changes: 4 additions & 0 deletions BaseStyle/BaseStyle.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
213F377E2C416C9C00972316 /* ScrollToTopButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 213F377D2C416C9C00972316 /* ScrollToTopButton.swift */; };
217620462C4F7CE700FED0D4 /* BackButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 217620452C4F7CE700FED0D4 /* BackButton.swift */; };
2176204A2C521EDF00FED0D4 /* RadioButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 217620492C521EDF00FED0D4 /* RadioButton.swift */; };
219F43D92CCA4A7000729C67 /* RestoreButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 219F43D82CCA4A7000729C67 /* RestoreButton.swift */; };
21BEF8A52C637E4900FBC9CF /* NavigationBarTopView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21BEF8A42C637E4900FBC9CF /* NavigationBarTopView.swift */; };
21BEF8A72C6399BA00FBC9CF /* BottomSheetHeightModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21BEF8A62C6399BA00FBC9CF /* BottomSheetHeightModifier.swift */; };
21D26E232CA199630090488B /* CapsuleButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21D26E222CA199610090488B /* CapsuleButton.swift */; };
Expand Down Expand Up @@ -72,6 +73,7 @@
213F377D2C416C9C00972316 /* ScrollToTopButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScrollToTopButton.swift; sourceTree = "<group>"; };
217620452C4F7CE700FED0D4 /* BackButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BackButton.swift; sourceTree = "<group>"; };
217620492C521EDF00FED0D4 /* RadioButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioButton.swift; sourceTree = "<group>"; };
219F43D82CCA4A7000729C67 /* RestoreButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RestoreButton.swift; sourceTree = "<group>"; };
21BEF8A42C637E4900FBC9CF /* NavigationBarTopView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationBarTopView.swift; sourceTree = "<group>"; };
21BEF8A62C6399BA00FBC9CF /* BottomSheetHeightModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BottomSheetHeightModifier.swift; sourceTree = "<group>"; };
21D26E222CA199610090488B /* CapsuleButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CapsuleButton.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -269,6 +271,7 @@
D8E244B42B972AD200C6C82A /* EmptyRouteView.swift */,
21BEF8A42C637E4900FBC9CF /* NavigationBarTopView.swift */,
21D614782CAD527D00779F1E /* NavigationTitleTextView.swift */,
219F43D82CCA4A7000729C67 /* RestoreButton.swift */,
);
path = Views;
sourceTree = "<group>";
Expand Down Expand Up @@ -523,6 +526,7 @@
2176204A2C521EDF00FED0D4 /* RadioButton.swift in Sources */,
D8302D9C2B9EE1D2005ACA13 /* PrimaryFloatingButton.swift in Sources */,
D887213F2B99992A009DC5BE /* LoaderViewModel.swift in Sources */,
219F43D92CCA4A7000729C67 /* RestoreButton.swift in Sources */,
D8D42AA32B8715B4009B345D /* TopViewController.swift in Sources */,
D89DBE332B888F2D00E5F1BD /* SearchBar.swift in Sources */,
D8D14A502BA090F000F45FF2 /* ShareSheetView.swift in Sources */,
Expand Down
6 changes: 4 additions & 2 deletions BaseStyle/BaseStyle/CustomUI/Buttons/PrimaryButton.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ public struct PrimaryButton: View {

@StateObject var loaderModel: LoaderViewModel = .init()

private let buttonHeight: CGFloat = 50

private let text: String
private var bgColor: Color
private var textColor: Color
Expand Down Expand Up @@ -55,9 +57,9 @@ public struct PrimaryButton: View {
.padding(.vertical, 15)
.minimumScaleFactor(0.5)
.background(isEnabled ? bgColor : bgColor.opacity(0.6))
.cornerRadius(12)
.clipShape(RoundedRectangle(cornerRadius: buttonHeight / 2))
}
.frame(minHeight: 50)
.frame(minHeight: buttonHeight)
.buttonStyle(.scale)
.disabled(!isEnabled || showLoader)
.opacity(showLoader ? 0.8 : 1)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"colors" : [
{
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

This file was deleted.

25 changes: 25 additions & 0 deletions BaseStyle/BaseStyle/Views/RestoreButton.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
//
// RestoreButton.swift
// Splito
//
// Created by Nirali Sonani on 24/10/24.
//

import SwiftUI

public struct RestoreButton: View {

let onClick: () -> Void

public init(onClick: @escaping () -> Void) {
self.onClick = onClick
}

public var body: some View {
Button(action: onClick) {
Text("Restore")
.font(.subTitle3())
.foregroundStyle(primaryText)
}
}
}
12 changes: 12 additions & 0 deletions Data/Data.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@

/* Begin PBXBuildFile section */
213D0CCA2C89DBC800D65C73 /* Notification+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 213D0CC92C89DBC800D65C73 /* Notification+Extension.swift */; };
21559CA42CBD05570039F127 /* ActivityLog.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21559CA32CBD05570039F127 /* ActivityLog.swift */; };
21559CAE2CBD2AED0039F127 /* ActivityLogStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21559CAD2CBD2AED0039F127 /* ActivityLogStore.swift */; };
21559CB02CBD2B400039F127 /* ActivityLogRepository.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21559CAF2CBD2B400039F127 /* ActivityLogRepository.swift */; };
21D8D0832C0857F10061B365 /* Constants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21D8D0822C0857F10061B365 /* Constants.swift */; };
64E499C5CFAEA368EC21313F /* Pods_DataTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1571EA0A08D442FEF7C09424 /* Pods_DataTests.framework */; };
7EF3A291581F7EA20CB1042D /* Pods_Data.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E91B3E23688435064A60C0C4 /* Pods_Data.framework */; };
Expand Down Expand Up @@ -64,6 +67,9 @@
/* Begin PBXFileReference section */
1571EA0A08D442FEF7C09424 /* Pods_DataTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_DataTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
213D0CC92C89DBC800D65C73 /* Notification+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Notification+Extension.swift"; sourceTree = "<group>"; };
21559CA32CBD05570039F127 /* ActivityLog.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActivityLog.swift; sourceTree = "<group>"; };
21559CAD2CBD2AED0039F127 /* ActivityLogStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActivityLogStore.swift; sourceTree = "<group>"; };
21559CAF2CBD2B400039F127 /* ActivityLogRepository.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActivityLogRepository.swift; sourceTree = "<group>"; };
21D8D0822C0857F10061B365 /* Constants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Constants.swift; sourceTree = "<group>"; };
5B14CF1A2EEF27479BF50566 /* Pods-DataTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-DataTests.debug.xcconfig"; path = "Target Support Files/Pods-DataTests/Pods-DataTests.debug.xcconfig"; sourceTree = "<group>"; };
803094012FE4C155F2A347B6 /* Pods-DataTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-DataTests.release.xcconfig"; path = "Target Support Files/Pods-DataTests/Pods-DataTests.release.xcconfig"; sourceTree = "<group>"; };
Expand Down Expand Up @@ -162,6 +168,7 @@
D83B15082B999789004A5F4F /* GroupRepository.swift */,
D85E86E42BAB088F002EDF76 /* ExpenseRepository.swift */,
D8CF5A242C199ADB0014E3AD /* TransactionRepository.swift */,
21559CAF2CBD2B400039F127 /* ActivityLogRepository.swift */,
D8D14A532BA092F400F45FF2 /* ShareCodeRepository.swift */,
);
path = Repository;
Expand All @@ -175,6 +182,7 @@
D83B15042B9996C0004A5F4F /* Groups.swift */,
D85E86DD2BAB0292002EDF76 /* Expense.swift */,
D8CF5A202C1986250014E3AD /* Transaction.swift */,
21559CA32CBD05570039F127 /* ActivityLog.swift */,
D8D14A512BA0917D00F45FF2 /* SharedCode.swift */,
);
path = Model;
Expand Down Expand Up @@ -229,6 +237,7 @@
D8A7CA762BA5AB800014EC67 /* GroupStore.swift */,
D8910E372BB6D1D300877CE0 /* ExpenseStore.swift */,
D8CF5A222C1989630014E3AD /* TransactionStore.swift */,
21559CAD2CBD2AED0039F127 /* ActivityLogStore.swift */,
D8A7CA7A2BA5B6AC0014EC67 /* ShareCodeStore.swift */,
);
path = Store;
Expand Down Expand Up @@ -511,7 +520,9 @@
D8D14A542BA092F500F45FF2 /* ShareCodeRepository.swift in Sources */,
D8A7CA7B2BA5B6AC0014EC67 /* ShareCodeStore.swift in Sources */,
D865F8AE2BD7CB0B0084BD36 /* Array+Extension.swift in Sources */,
21559CB02CBD2B400039F127 /* ActivityLogRepository.swift in Sources */,
D89DBE2B2B88817E00E5F1BD /* JSONUtils.swift in Sources */,
21559CA42CBD05570039F127 /* ActivityLog.swift in Sources */,
D8A7CA802BA867F80014EC67 /* String+Extension.swift in Sources */,
213D0CCA2C89DBC800D65C73 /* Notification+Extension.swift in Sources */,
D895F2282CA297B900C2E4EB /* NetworkManager.swift in Sources */,
Expand All @@ -532,6 +543,7 @@
D89DBE1D2B872F0B00E5F1BD /* NonceGenerator.swift in Sources */,
D85E86DE2BAB0292002EDF76 /* Expense.swift in Sources */,
D8D42AA92B872726009B345D /* DDLogProvider.swift in Sources */,
21559CAE2CBD2AED0039F127 /* ActivityLogStore.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down
8 changes: 8 additions & 0 deletions Data/Data/DI/AppAssembly.swift
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ public class AppAssembly: Assembly {
UserStore.init()
}.inObjectScope(.container)

container.register(ActivityLogStore.self) { _ in
ActivityLogStore.init()
}.inObjectScope(.container)

container.register(GroupStore.self) { _ in
GroupStore.init()
}.inObjectScope(.container)
Expand All @@ -63,6 +67,10 @@ public class AppAssembly: Assembly {
UserRepository.init()
}.inObjectScope(.container)

container.register(ActivityLogRepository.self) { _ in
ActivityLogRepository.init()
}.inObjectScope(.container)

container.register(GroupRepository.self) { _ in
GroupRepository.init()
}.inObjectScope(.container)
Expand Down
61 changes: 61 additions & 0 deletions Data/Data/Extension/Date+Extension.swift
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,64 @@ public extension Date {
return Date()
}
}

public extension Date {
func isToday() -> Bool {
return Calendar.current.isDateInToday(self)
}

func isYesterday() -> Bool {
return Calendar.current.isDateInYesterday(self)
}

func get(_ components: Calendar.Component..., calendar: Calendar = Calendar.current) -> DateComponents {
return calendar.dateComponents(Set(components), from: self)
}

func getDateIn(format: String) -> String {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = format
return dateFormatter.string(from: self)
}
}

public extension Date {
/// This will return string of formatted time with respect to current time in format of **"1 minute ago", "1 hour ago", "10: 30 PM Yesterday", "10:30 AM 01, Jan" or "10:30 AM 01, Jan 1970"**
func getFormattedPastTime() -> String {
let currentTime = Date()
if isToday() {
let dateSeconds = Int(self.timeIntervalSince1970)
let currentTimeSeconds = Int(currentTime.timeIntervalSince1970)
if (currentTimeSeconds - dateSeconds) < 60 {
return "Just now"
} else if (currentTimeSeconds - dateSeconds) < (60*60) {
return "\(Int(currentTimeSeconds - dateSeconds)/60)" + " " + "min ago"
} else {
let hours = Int((currentTimeSeconds - dateSeconds)/(60*60))
if hours < 2 {
return "\(hours)" + " " + "hour ago"
} else {
return "\(hours)" + " " + "hours ago"
}
}
} else if isYesterday() {
if isTimeIn24HourFormat {
return "Yesterday" + " " + self.getDateIn(format: "HH:mm")
} else {
return "Yesterday" + " " + self.getDateIn(format: "hh:mm a")
}
} else {
let isSameYear = self.get(.year).year == Date().get(.year).year
if isTimeIn24HourFormat {
return self.getDateIn(format: isSameYear ? "dd MMM, HH:mm" : "dd MMMM yyyy, HH:mm")
} else {
return self.getDateIn(format: isSameYear ? "dd MMM, hh:mm a" : "dd MMMM yyyy, hh:mm a")
}
}
}
}

public var isTimeIn24HourFormat: Bool {
let dateFormat = DateFormatter.dateFormat(fromTemplate: "j", options: 0, locale: Locale.current)
return dateFormat == "HH"
}
15 changes: 13 additions & 2 deletions Data/Data/Extension/Double+Extension.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,26 @@
import Foundation

public extension Double {
var formattedCurrency: String {
func formattedCurrency(removeMinusSign: Bool = true) -> String {
let formatter = NumberFormatter()
formatter.numberStyle = .currency
formatter.locale = Locale.current

if let formattedAmount = formatter.string(from: NSNumber(value: self)) {
return formattedAmount.hasPrefix("-") ? String(formattedAmount.dropFirst()) : formattedAmount
if removeMinusSign && formattedAmount.hasPrefix("-") {
return String(formattedAmount.dropFirst())
}
return formattedAmount
} else {
return String(format: "%.2f", self.rounded()) // Fallback to a basic decimal format
}
}

var formattedCurrency: String {
return formattedCurrency(removeMinusSign: true)
}

var formattedCurrencyWithSign: String {
return formattedCurrency(removeMinusSign: false)
}
}
2 changes: 2 additions & 0 deletions Data/Data/Extension/Notification+Extension.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,6 @@ public extension Notification.Name {
static let updateGroup = Notification.Name("updateGroup")
static let deleteGroup = Notification.Name("deleteGroup")
static let leaveGroup = Notification.Name("leaveGroup")

static let showActivityLog = Notification.Name("showActivityLog")
}
2 changes: 1 addition & 1 deletion Data/Data/Extension/Timestamp+Extension.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import Foundation
import FirebaseFirestore

extension Timestamp: @retroactive Comparable {
extension Timestamp {
public static func < (lhs: Timestamp, rhs: Timestamp) -> Bool {
return lhs.dateValue() < rhs.dateValue()
}
Expand Down
84 changes: 84 additions & 0 deletions Data/Data/Model/ActivityLog.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
//
// ActivityLog.swift
// Data
//
// Created by Nirali Sonani on 14/10/24.
//

import FirebaseFirestore

public struct ActivityLog: Codable, Identifiable, Hashable {

@DocumentID public var id: String? // Automatically generated ID by Firestore

/// The type of activity (e.g., group created, expense updated)
public let type: ActivityType
public let groupId: String

/// The id of the activity (e.g., expense or transaction)
public let activityId: String
public let groupName: String

/// The name of the user who performed the action
public let actionUserName: String
public let recordedOn: Timestamp
public let previousGroupName: String?
public let removedMemberName: String?
public let expenseName: String?
public let payerName: String?
public let receiverName: String?
public let amount: Double?

public init(type: ActivityType, groupId: String, activityId: String, groupName: String, actionUserName: String,
recordedOn: Timestamp, previousGroupName: String? = nil, removedMemberName: String? = nil,
expenseName: String? = nil, payerName: String? = nil, receiverName: String? = nil, amount: Double? = nil) {
self.type = type
self.groupId = groupId
self.activityId = activityId
self.groupName = groupName
self.actionUserName = actionUserName
self.recordedOn = recordedOn
self.previousGroupName = previousGroupName
self.removedMemberName = removedMemberName
self.expenseName = expenseName
self.payerName = payerName
self.receiverName = receiverName
self.amount = amount
}

enum CodingKeys: String, CodingKey {
case id
case type
case groupId = "group_id"
case activityId = "activity_id"
case groupName = "group_name"
case actionUserName = "action_user_name"
case recordedOn = "recorded_on"
case previousGroupName = "previous_group_name"
case removedMemberName = "removed_member_name"
case expenseName = "expense_name"
case payerName = "payer_name"
case receiverName = "receiver_name"
case amount
}
}

public enum ActivityType: String, Codable {
case none
case groupCreated = "group_created"
case groupUpdated = "group_updated"
case groupDeleted = "group_deleted"
case groupRestored = "group_restored"
case groupNameUpdated = "group_name_updated"
case groupImageUpdated = "group_image_updated"
case groupMemberLeft = "group_member_left"
case groupMemberRemoved = "group_member_removed"
case expenseAdded = "expense_added"
case expenseUpdated = "expense_updated"
case expenseDeleted = "expense_deleted"
case expenseRestored = "expense_restored"
case transactionAdded = "transaction_added"
case transactionUpdated = "transaction_updated"
case transactionDeleted = "transaction_deleted"
case transactionRestored = "transaction_restored"
}
Loading

0 comments on commit ce8c6f8

Please sign in to comment.