brakedown by week and month

This commit is contained in:
José Salazar
2026-01-26 17:51:30 -05:00
parent f65121a26f
commit fd06391e63
19 changed files with 18566 additions and 17804 deletions

View File

@@ -1,11 +1,13 @@
// This is a generated file; do not edit or check into version control.
FLUTTER_ROOT=/Users/achinthaisuru/Documents/flutter
FLUTTER_APPLICATION_PATH=/Users/achinthaisuru/Documents/Github/krow-workforce/apps/mobile/apps/client
FLUTTER_ROOT=/Users/josesalazar/flutter
FLUTTER_APPLICATION_PATH=/Users/josesalazar/Documents/DEV/krow-workforce/apps/mobile/apps/client
COCOAPODS_PARALLEL_CODE_SIGN=true
FLUTTER_TARGET=/Users/josesalazar/Documents/DEV/krow-workforce/apps/mobile/apps/client/lib/main.dart
FLUTTER_BUILD_DIR=build
FLUTTER_BUILD_NAME=1.0.0
FLUTTER_BUILD_NUMBER=1
DART_DEFINES=RkxVVFRFUl9WRVJTSU9OPTMuMzguNw==,RkxVVFRFUl9DSEFOTkVMPXN0YWJsZQ==,RkxVVFRFUl9HSVRfVVJMPWh0dHBzOi8vZ2l0aHViLmNvbS9mbHV0dGVyL2ZsdXR0ZXIuZ2l0,RkxVVFRFUl9GUkFNRVdPUktfUkVWSVNJT049M2I2MmVmYzJhMw==,RkxVVFRFUl9FTkdJTkVfUkVWSVNJT049NzhmYzMwMTJlNA==,RkxVVFRFUl9EQVJUX1ZFUlNJT049My4xMC43
DART_OBFUSCATION=false
TRACK_WIDGET_CREATION=true
TREE_SHAKE_ICONS=false
PACKAGE_CONFIG=.dart_tool/package_config.json
PACKAGE_CONFIG=/Users/josesalazar/Documents/DEV/krow-workforce/apps/mobile/.dart_tool/package_config.json

View File

@@ -1,12 +1,14 @@
#!/bin/sh
# This is a generated file; do not edit or check into version control.
export "FLUTTER_ROOT=/Users/achinthaisuru/Documents/flutter"
export "FLUTTER_APPLICATION_PATH=/Users/achinthaisuru/Documents/Github/krow-workforce/apps/mobile/apps/client"
export "FLUTTER_ROOT=/Users/josesalazar/flutter"
export "FLUTTER_APPLICATION_PATH=/Users/josesalazar/Documents/DEV/krow-workforce/apps/mobile/apps/client"
export "COCOAPODS_PARALLEL_CODE_SIGN=true"
export "FLUTTER_TARGET=/Users/josesalazar/Documents/DEV/krow-workforce/apps/mobile/apps/client/lib/main.dart"
export "FLUTTER_BUILD_DIR=build"
export "FLUTTER_BUILD_NAME=1.0.0"
export "FLUTTER_BUILD_NUMBER=1"
export "DART_DEFINES=RkxVVFRFUl9WRVJTSU9OPTMuMzguNw==,RkxVVFRFUl9DSEFOTkVMPXN0YWJsZQ==,RkxVVFRFUl9HSVRfVVJMPWh0dHBzOi8vZ2l0aHViLmNvbS9mbHV0dGVyL2ZsdXR0ZXIuZ2l0,RkxVVFRFUl9GUkFNRVdPUktfUkVWSVNJT049M2I2MmVmYzJhMw==,RkxVVFRFUl9FTkdJTkVfUkVWSVNJT049NzhmYzMwMTJlNA==,RkxVVFRFUl9EQVJUX1ZFUlNJT049My4xMC43"
export "DART_OBFUSCATION=false"
export "TRACK_WIDGET_CREATION=true"
export "TREE_SHAKE_ICONS=false"
export "PACKAGE_CONFIG=.dart_tool/package_config.json"
export "PACKAGE_CONFIG=/Users/josesalazar/Documents/DEV/krow-workforce/apps/mobile/.dart_tool/package_config.json"

View File

@@ -0,0 +1,144 @@
PODS:
- AppCheckCore (11.2.0):
- GoogleUtilities/Environment (~> 8.0)
- GoogleUtilities/UserDefaults (~> 8.0)
- PromisesObjC (~> 2.4)
- Firebase/AppCheck (12.8.0):
- Firebase/CoreOnly
- FirebaseAppCheck (~> 12.8.0)
- Firebase/Auth (12.8.0):
- Firebase/CoreOnly
- FirebaseAuth (~> 12.8.0)
- Firebase/CoreOnly (12.8.0):
- FirebaseCore (~> 12.8.0)
- firebase_app_check (0.4.1-4):
- Firebase/AppCheck (~> 12.8.0)
- Firebase/CoreOnly (~> 12.8.0)
- firebase_core
- FlutterMacOS
- firebase_auth (6.1.4):
- Firebase/Auth (~> 12.8.0)
- Firebase/CoreOnly (~> 12.8.0)
- firebase_core
- FlutterMacOS
- firebase_core (4.4.0):
- Firebase/CoreOnly (~> 12.8.0)
- FlutterMacOS
- FirebaseAppCheck (12.8.0):
- AppCheckCore (~> 11.0)
- FirebaseAppCheckInterop (~> 12.8.0)
- FirebaseCore (~> 12.8.0)
- GoogleUtilities/Environment (~> 8.1)
- GoogleUtilities/UserDefaults (~> 8.1)
- FirebaseAppCheckInterop (12.8.0)
- FirebaseAuth (12.8.0):
- FirebaseAppCheckInterop (~> 12.8.0)
- FirebaseAuthInterop (~> 12.8.0)
- FirebaseCore (~> 12.8.0)
- FirebaseCoreExtension (~> 12.8.0)
- GoogleUtilities/AppDelegateSwizzler (~> 8.1)
- GoogleUtilities/Environment (~> 8.1)
- GTMSessionFetcher/Core (< 6.0, >= 3.4)
- RecaptchaInterop (~> 101.0)
- FirebaseAuthInterop (12.8.0)
- FirebaseCore (12.8.0):
- FirebaseCoreInternal (~> 12.8.0)
- GoogleUtilities/Environment (~> 8.1)
- GoogleUtilities/Logger (~> 8.1)
- FirebaseCoreExtension (12.8.0):
- FirebaseCore (~> 12.8.0)
- FirebaseCoreInternal (12.8.0):
- "GoogleUtilities/NSData+zlib (~> 8.1)"
- FlutterMacOS (1.0.0)
- GoogleUtilities/AppDelegateSwizzler (8.1.0):
- GoogleUtilities/Environment
- GoogleUtilities/Logger
- GoogleUtilities/Network
- GoogleUtilities/Privacy
- GoogleUtilities/Environment (8.1.0):
- GoogleUtilities/Privacy
- GoogleUtilities/Logger (8.1.0):
- GoogleUtilities/Environment
- GoogleUtilities/Privacy
- GoogleUtilities/Network (8.1.0):
- GoogleUtilities/Logger
- "GoogleUtilities/NSData+zlib"
- GoogleUtilities/Privacy
- GoogleUtilities/Reachability
- "GoogleUtilities/NSData+zlib (8.1.0)":
- GoogleUtilities/Privacy
- GoogleUtilities/Privacy (8.1.0)
- GoogleUtilities/Reachability (8.1.0):
- GoogleUtilities/Logger
- GoogleUtilities/Privacy
- GoogleUtilities/UserDefaults (8.1.0):
- GoogleUtilities/Logger
- GoogleUtilities/Privacy
- GTMSessionFetcher/Core (5.0.0)
- PromisesObjC (2.4.0)
- shared_preferences_foundation (0.0.1):
- Flutter
- FlutterMacOS
- url_launcher_macos (0.0.1):
- FlutterMacOS
DEPENDENCIES:
- firebase_app_check (from `Flutter/ephemeral/.symlinks/plugins/firebase_app_check/macos`)
- firebase_auth (from `Flutter/ephemeral/.symlinks/plugins/firebase_auth/macos`)
- firebase_core (from `Flutter/ephemeral/.symlinks/plugins/firebase_core/macos`)
- FlutterMacOS (from `Flutter/ephemeral`)
- shared_preferences_foundation (from `Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin`)
- url_launcher_macos (from `Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos`)
SPEC REPOS:
trunk:
- AppCheckCore
- Firebase
- FirebaseAppCheck
- FirebaseAppCheckInterop
- FirebaseAuth
- FirebaseAuthInterop
- FirebaseCore
- FirebaseCoreExtension
- FirebaseCoreInternal
- GoogleUtilities
- GTMSessionFetcher
- PromisesObjC
EXTERNAL SOURCES:
firebase_app_check:
:path: Flutter/ephemeral/.symlinks/plugins/firebase_app_check/macos
firebase_auth:
:path: Flutter/ephemeral/.symlinks/plugins/firebase_auth/macos
firebase_core:
:path: Flutter/ephemeral/.symlinks/plugins/firebase_core/macos
FlutterMacOS:
:path: Flutter/ephemeral
shared_preferences_foundation:
:path: Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin
url_launcher_macos:
:path: Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos
SPEC CHECKSUMS:
AppCheckCore: cc8fd0a3a230ddd401f326489c99990b013f0c4f
Firebase: 9a58fdbc9d8655ed7b79a19cf9690bb007d3d46d
firebase_app_check: daf97f2d7044e28b68d23bc90e16751acee09732
firebase_auth: 2c2438e41f061c03bd67dcb045dfd7bc843b5f52
firebase_core: b1697fb64ff2b9ca16baaa821205f8b0c058e5d2
FirebaseAppCheck: 11da425929a45c677d537adfff3520ccd57c1690
FirebaseAppCheckInterop: ba3dc604a89815379e61ec2365101608d365cf7d
FirebaseAuth: 4c289b1a43f5955283244a55cf6bd616de344be5
FirebaseAuthInterop: 95363fe96493cb4f106656666a0768b420cba090
FirebaseCore: 0dbad74bda10b8fb9ca34ad8f375fb9dd3ebef7c
FirebaseCoreExtension: 6605938d51f765d8b18bfcafd2085276a252bee2
FirebaseCoreInternal: fe5fa466aeb314787093a7dce9f0beeaad5a2a21
FlutterMacOS: d0db08ddef1a9af05a5ec4b724367152bb0500b1
GoogleUtilities: 00c88b9a86066ef77f0da2fab05f65d7768ed8e1
GTMSessionFetcher: 02d6e866e90bc236f48a703a041dfe43e6221a29
PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47
shared_preferences_foundation: 7036424c3d8ec98dfe75ff1667cb0cd531ec82bb
url_launcher_macos: f87a979182d112f911de6820aefddaf56ee9fbfd
PODFILE CHECKSUM: 54d867c82ac51cbd61b565781b9fada492027009
COCOAPODS: 1.16.2

View File

@@ -21,12 +21,14 @@
/* End PBXAggregateTarget section */
/* Begin PBXBuildFile section */
0F4B527ECDE4F2B2C670C976 /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E7312AB7BD5F6DDA3D35C363 /* Pods_RunnerTests.framework */; };
331C80D8294CF71000263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C80D7294CF71000263BE5 /* RunnerTests.swift */; };
335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */; };
33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC10F02044A3C60003C045 /* AppDelegate.swift */; };
33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; };
33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; };
33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; };
9DB7E3A540BFA4257A1E28F2 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 37067E162A87D9CF2CE23CE4 /* Pods_Runner.framework */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
@@ -60,11 +62,12 @@
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
3235450CFBBC51513BBB882F /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; };
331C80D5294CF71000263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
331C80D7294CF71000263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = "<group>"; };
333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = "<group>"; };
335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = "<group>"; };
33CC10ED2044A3C60003C045 /* krow_client.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "krow_client.app"; sourceTree = BUILT_PRODUCTS_DIR; };
33CC10ED2044A3C60003C045 /* krow_client.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = krow_client.app; sourceTree = BUILT_PRODUCTS_DIR; };
33CC10F02044A3C60003C045 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
33CC10F22044A3C60003C045 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = Runner/Assets.xcassets; sourceTree = "<group>"; };
33CC10F52044A3C60003C045 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = "<group>"; };
@@ -76,8 +79,15 @@
33E51913231747F40026EE4D /* DebugProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DebugProfile.entitlements; sourceTree = "<group>"; };
33E51914231749380026EE4D /* Release.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Release.entitlements; sourceTree = "<group>"; };
33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = "<group>"; };
37067E162A87D9CF2CE23CE4 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
52BFCC2D82C3A8048E275DF3 /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = "<group>"; };
54AD243DC5A5AF26694848AC /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = "<group>"; };
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = "<group>"; };
8E21FE29E642AD2A9B5E46C9 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; };
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = "<group>"; };
E0E474066D036677DFE3795B /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
E7312AB7BD5F6DDA3D35C363 /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
FF54856CCC3D0D2B521DE3D2 /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -85,6 +95,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
0F4B527ECDE4F2B2C670C976 /* Pods_RunnerTests.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -92,6 +103,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
9DB7E3A540BFA4257A1E28F2 /* Pods_Runner.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -125,6 +137,7 @@
331C80D6294CF71000263BE5 /* RunnerTests */,
33CC10EE2044A3C60003C045 /* Products */,
D73912EC22F37F3D000D13A0 /* Frameworks */,
F114226C38150965DB02851D /* Pods */,
);
sourceTree = "<group>";
};
@@ -175,10 +188,26 @@
D73912EC22F37F3D000D13A0 /* Frameworks */ = {
isa = PBXGroup;
children = (
37067E162A87D9CF2CE23CE4 /* Pods_Runner.framework */,
E7312AB7BD5F6DDA3D35C363 /* Pods_RunnerTests.framework */,
);
name = Frameworks;
sourceTree = "<group>";
};
F114226C38150965DB02851D /* Pods */ = {
isa = PBXGroup;
children = (
8E21FE29E642AD2A9B5E46C9 /* Pods-Runner.debug.xcconfig */,
E0E474066D036677DFE3795B /* Pods-Runner.release.xcconfig */,
3235450CFBBC51513BBB882F /* Pods-Runner.profile.xcconfig */,
FF54856CCC3D0D2B521DE3D2 /* Pods-RunnerTests.debug.xcconfig */,
54AD243DC5A5AF26694848AC /* Pods-RunnerTests.release.xcconfig */,
52BFCC2D82C3A8048E275DF3 /* Pods-RunnerTests.profile.xcconfig */,
);
name = Pods;
path = Pods;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
@@ -186,6 +215,7 @@
isa = PBXNativeTarget;
buildConfigurationList = 331C80DE294CF71000263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */;
buildPhases = (
1F1C8C8AD94BD1FFF3970EA2 /* [CP] Check Pods Manifest.lock */,
331C80D1294CF70F00263BE5 /* Sources */,
331C80D2294CF70F00263BE5 /* Frameworks */,
331C80D3294CF70F00263BE5 /* Resources */,
@@ -204,11 +234,13 @@
isa = PBXNativeTarget;
buildConfigurationList = 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */;
buildPhases = (
13A75D879CCA17A67E27F169 /* [CP] Check Pods Manifest.lock */,
33CC10E92044A3C60003C045 /* Sources */,
33CC10EA2044A3C60003C045 /* Frameworks */,
33CC10EB2044A3C60003C045 /* Resources */,
33CC110E2044A8840003C045 /* Bundle Framework */,
3399D490228B24CF009A79C7 /* ShellScript */,
D0A48B88512859849D0E92D6 /* [CP] Embed Pods Frameworks */,
);
buildRules = (
);
@@ -291,6 +323,50 @@
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
13A75D879CCA17A67E27F169 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
"${PODS_ROOT}/Manifest.lock",
);
name = "[CP] Check Pods Manifest.lock";
outputFileListPaths = (
);
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
1F1C8C8AD94BD1FFF3970EA2 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
"${PODS_ROOT}/Manifest.lock",
);
name = "[CP] Check Pods Manifest.lock";
outputFileListPaths = (
);
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-RunnerTests-checkManifestLockResult.txt",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
3399D490228B24CF009A79C7 /* ShellScript */ = {
isa = PBXShellScriptBuildPhase;
alwaysOutOfDate = 1;
@@ -329,6 +405,23 @@
shellPath = /bin/sh;
shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh && touch Flutter/ephemeral/tripwire";
};
D0A48B88512859849D0E92D6 /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
);
name = "[CP] Embed Pods Frameworks";
outputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
@@ -380,6 +473,7 @@
/* Begin XCBuildConfiguration section */
331C80DB294CF71000263BE5 /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = FF54856CCC3D0D2B521DE3D2 /* Pods-RunnerTests.debug.xcconfig */;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CURRENT_PROJECT_VERSION = 1;
@@ -394,6 +488,7 @@
};
331C80DC294CF71000263BE5 /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 54AD243DC5A5AF26694848AC /* Pods-RunnerTests.release.xcconfig */;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CURRENT_PROJECT_VERSION = 1;
@@ -408,6 +503,7 @@
};
331C80DD294CF71000263BE5 /* Profile */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 52BFCC2D82C3A8048E275DF3 /* Pods-RunnerTests.profile.xcconfig */;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CURRENT_PROJECT_VERSION = 1;

View File

@@ -4,4 +4,7 @@
<FileRef
location = "group:Runner.xcodeproj">
</FileRef>
<FileRef
location = "group:Pods/Pods.xcodeproj">
</FileRef>
</Workspace>

View File

@@ -1,16 +1,16 @@
# Basic Usage
```dart
ExampleConnector.instance.createWorkforce(createWorkforceVariables).execute();
ExampleConnector.instance.updateWorkforce(updateWorkforceVariables).execute();
ExampleConnector.instance.deactivateWorkforce(deactivateWorkforceVariables).execute();
ExampleConnector.instance.listInvoices(listInvoicesVariables).execute();
ExampleConnector.instance.getInvoiceById(getInvoiceByIdVariables).execute();
ExampleConnector.instance.listInvoicesByVendorId(listInvoicesByVendorIdVariables).execute();
ExampleConnector.instance.listInvoicesByBusinessId(listInvoicesByBusinessIdVariables).execute();
ExampleConnector.instance.listInvoicesByOrderId(listInvoicesByOrderIdVariables).execute();
ExampleConnector.instance.listInvoicesByStatus(listInvoicesByStatusVariables).execute();
ExampleConnector.instance.filterInvoices(filterInvoicesVariables).execute();
ExampleConnector.instance.listBusinesses().execute();
ExampleConnector.instance.getBusinessesByUserId(getBusinessesByUserIdVariables).execute();
ExampleConnector.instance.getBusinessById(getBusinessByIdVariables).execute();
ExampleConnector.instance.createInvoice(createInvoiceVariables).execute();
ExampleConnector.instance.updateInvoice(updateInvoiceVariables).execute();
ExampleConnector.instance.deleteInvoice(deleteInvoiceVariables).execute();
ExampleConnector.instance.listRoles().execute();
ExampleConnector.instance.getRoleById(getRoleByIdVariables).execute();
ExampleConnector.instance.listRolesByVendorId(listRolesByVendorIdVariables).execute();
ExampleConnector.instance.listRolesByroleCategoryId(listRolesByroleCategoryIdVariables).execute();
```
@@ -23,8 +23,8 @@ Optional fields can be discovered based on classes that have `Optional` object t
This is an example of a mutation with an optional field:
```dart
await ExampleConnector.instance.updateVendor({ ... })
.companyName(...)
await ExampleConnector.instance.UpdateAssignment({ ... })
.title(...)
.execute();
```

View File

@@ -0,0 +1,229 @@
part of 'generated.dart';
class ListShiftRolesByBusinessAndDatesSummaryVariablesBuilder {
String businessId;
Timestamp start;
Timestamp end;
Optional<int> _offset = Optional.optional(nativeFromJson, nativeToJson);
Optional<int> _limit = Optional.optional(nativeFromJson, nativeToJson);
final FirebaseDataConnect _dataConnect; ListShiftRolesByBusinessAndDatesSummaryVariablesBuilder offset(int? t) {
_offset.value = t;
return this;
}
ListShiftRolesByBusinessAndDatesSummaryVariablesBuilder limit(int? t) {
_limit.value = t;
return this;
}
ListShiftRolesByBusinessAndDatesSummaryVariablesBuilder(this._dataConnect, {required this.businessId,required this.start,required this.end,});
Deserializer<ListShiftRolesByBusinessAndDatesSummaryData> dataDeserializer = (dynamic json) => ListShiftRolesByBusinessAndDatesSummaryData.fromJson(jsonDecode(json));
Serializer<ListShiftRolesByBusinessAndDatesSummaryVariables> varsSerializer = (ListShiftRolesByBusinessAndDatesSummaryVariables vars) => jsonEncode(vars.toJson());
Future<QueryResult<ListShiftRolesByBusinessAndDatesSummaryData, ListShiftRolesByBusinessAndDatesSummaryVariables>> execute() {
return ref().execute();
}
QueryRef<ListShiftRolesByBusinessAndDatesSummaryData, ListShiftRolesByBusinessAndDatesSummaryVariables> ref() {
ListShiftRolesByBusinessAndDatesSummaryVariables vars= ListShiftRolesByBusinessAndDatesSummaryVariables(businessId: businessId,start: start,end: end,offset: _offset,limit: _limit,);
return _dataConnect.query("listShiftRolesByBusinessAndDatesSummary", dataDeserializer, varsSerializer, vars);
}
}
@immutable
class ListShiftRolesByBusinessAndDatesSummaryShiftRoles {
final String roleId;
final double? hours;
final double? totalValue;
final ListShiftRolesByBusinessAndDatesSummaryShiftRolesRole role;
ListShiftRolesByBusinessAndDatesSummaryShiftRoles.fromJson(dynamic json):
roleId = nativeFromJson<String>(json['roleId']),
hours = json['hours'] == null ? null : nativeFromJson<double>(json['hours']),
totalValue = json['totalValue'] == null ? null : nativeFromJson<double>(json['totalValue']),
role = ListShiftRolesByBusinessAndDatesSummaryShiftRolesRole.fromJson(json['role']);
@override
bool operator ==(Object other) {
if(identical(this, other)) {
return true;
}
if(other.runtimeType != runtimeType) {
return false;
}
final ListShiftRolesByBusinessAndDatesSummaryShiftRoles otherTyped = other as ListShiftRolesByBusinessAndDatesSummaryShiftRoles;
return roleId == otherTyped.roleId &&
hours == otherTyped.hours &&
totalValue == otherTyped.totalValue &&
role == otherTyped.role;
}
@override
int get hashCode => Object.hashAll([roleId.hashCode, hours.hashCode, totalValue.hashCode, role.hashCode]);
Map<String, dynamic> toJson() {
Map<String, dynamic> json = {};
json['roleId'] = nativeToJson<String>(roleId);
if (hours != null) {
json['hours'] = nativeToJson<double?>(hours);
}
if (totalValue != null) {
json['totalValue'] = nativeToJson<double?>(totalValue);
}
json['role'] = role.toJson();
return json;
}
ListShiftRolesByBusinessAndDatesSummaryShiftRoles({
required this.roleId,
this.hours,
this.totalValue,
required this.role,
});
}
@immutable
class ListShiftRolesByBusinessAndDatesSummaryShiftRolesRole {
final String id;
final String name;
ListShiftRolesByBusinessAndDatesSummaryShiftRolesRole.fromJson(dynamic json):
id = nativeFromJson<String>(json['id']),
name = nativeFromJson<String>(json['name']);
@override
bool operator ==(Object other) {
if(identical(this, other)) {
return true;
}
if(other.runtimeType != runtimeType) {
return false;
}
final ListShiftRolesByBusinessAndDatesSummaryShiftRolesRole otherTyped = other as ListShiftRolesByBusinessAndDatesSummaryShiftRolesRole;
return id == otherTyped.id &&
name == otherTyped.name;
}
@override
int get hashCode => Object.hashAll([id.hashCode, name.hashCode]);
Map<String, dynamic> toJson() {
Map<String, dynamic> json = {};
json['id'] = nativeToJson<String>(id);
json['name'] = nativeToJson<String>(name);
return json;
}
ListShiftRolesByBusinessAndDatesSummaryShiftRolesRole({
required this.id,
required this.name,
});
}
@immutable
class ListShiftRolesByBusinessAndDatesSummaryData {
final List<ListShiftRolesByBusinessAndDatesSummaryShiftRoles> shiftRoles;
ListShiftRolesByBusinessAndDatesSummaryData.fromJson(dynamic json):
shiftRoles = (json['shiftRoles'] as List<dynamic>)
.map((e) => ListShiftRolesByBusinessAndDatesSummaryShiftRoles.fromJson(e))
.toList();
@override
bool operator ==(Object other) {
if(identical(this, other)) {
return true;
}
if(other.runtimeType != runtimeType) {
return false;
}
final ListShiftRolesByBusinessAndDatesSummaryData otherTyped = other as ListShiftRolesByBusinessAndDatesSummaryData;
return shiftRoles == otherTyped.shiftRoles;
}
@override
int get hashCode => shiftRoles.hashCode;
Map<String, dynamic> toJson() {
Map<String, dynamic> json = {};
json['shiftRoles'] = shiftRoles.map((e) => e.toJson()).toList();
return json;
}
ListShiftRolesByBusinessAndDatesSummaryData({
required this.shiftRoles,
});
}
@immutable
class ListShiftRolesByBusinessAndDatesSummaryVariables {
final String businessId;
final Timestamp start;
final Timestamp end;
late final Optional<int>offset;
late final Optional<int>limit;
@Deprecated('fromJson is deprecated for Variable classes as they are no longer required for deserialization.')
ListShiftRolesByBusinessAndDatesSummaryVariables.fromJson(Map<String, dynamic> json):
businessId = nativeFromJson<String>(json['businessId']),
start = Timestamp.fromJson(json['start']),
end = Timestamp.fromJson(json['end']) {
offset = Optional.optional(nativeFromJson, nativeToJson);
offset.value = json['offset'] == null ? null : nativeFromJson<int>(json['offset']);
limit = Optional.optional(nativeFromJson, nativeToJson);
limit.value = json['limit'] == null ? null : nativeFromJson<int>(json['limit']);
}
@override
bool operator ==(Object other) {
if(identical(this, other)) {
return true;
}
if(other.runtimeType != runtimeType) {
return false;
}
final ListShiftRolesByBusinessAndDatesSummaryVariables otherTyped = other as ListShiftRolesByBusinessAndDatesSummaryVariables;
return businessId == otherTyped.businessId &&
start == otherTyped.start &&
end == otherTyped.end &&
offset == otherTyped.offset &&
limit == otherTyped.limit;
}
@override
int get hashCode => Object.hashAll([businessId.hashCode, start.hashCode, end.hashCode, offset.hashCode, limit.hashCode]);
Map<String, dynamic> toJson() {
Map<String, dynamic> json = {};
json['businessId'] = nativeToJson<String>(businessId);
json['start'] = start.toJson();
json['end'] = end.toJson();
if(offset.state == OptionalState.set) {
json['offset'] = offset.toJson();
}
if(limit.state == OptionalState.set) {
json['limit'] = limit.toJson();
}
return json;
}
ListShiftRolesByBusinessAndDatesSummaryVariables({
required this.businessId,
required this.start,
required this.end,
required this.offset,
required this.limit,
});
}

View File

@@ -23,6 +23,7 @@ class BillingModule extends Module {
i.addSingleton<BillingRepository>(
() => BillingRepositoryImpl(
financialRepository: i.get<FinancialRepositoryMock>(),
dataConnect: ExampleConnector.instance,
),
);

View File

@@ -1,5 +1,7 @@
import 'package:firebase_data_connect/firebase_data_connect.dart' as fdc;
import 'package:krow_data_connect/krow_data_connect.dart' as data_connect;
import 'package:krow_domain/krow_domain.dart';
import '../../domain/models/billing_period.dart';
import '../../domain/repositories/billing_repository.dart';
/// Implementation of [BillingRepository] in the Data layer.
@@ -16,9 +18,12 @@ class BillingRepositoryImpl implements BillingRepository {
/// Requires the [financialRepository] to fetch financial data.
BillingRepositoryImpl({
required data_connect.FinancialRepositoryMock financialRepository,
}) : _financialRepository = financialRepository;
required data_connect.ExampleConnector dataConnect,
}) : _financialRepository = financialRepository,
_dataConnect = dataConnect;
final data_connect.FinancialRepositoryMock _financialRepository;
final data_connect.ExampleConnector _dataConnect;
/// Fetches the current bill amount by aggregating open invoices.
@override
@@ -72,9 +77,114 @@ class BillingRepositoryImpl implements BillingRepository {
/// Fetches the breakdown of spending.
@override
Future<List<InvoiceItem>> getSpendingBreakdown() async {
// Assuming breakdown is based on the current period's invoice items.
// We fetch items for a dummy invoice ID representing the current period.
return _financialRepository.getInvoiceItems('current_period_invoice');
Future<List<InvoiceItem>> getSpendingBreakdown(BillingPeriod period) async {
final String? businessId =
data_connect.ClientSessionStore.instance.session?.business?.id;
if (businessId == null || businessId.isEmpty) {
return <InvoiceItem>[];
}
final DateTime now = DateTime.now();
final DateTime start;
final DateTime end;
if (period == BillingPeriod.week) {
final int daysFromMonday = now.weekday - DateTime.monday;
final DateTime monday = DateTime(
now.year,
now.month,
now.day,
).subtract(Duration(days: daysFromMonday));
start = DateTime(monday.year, monday.month, monday.day);
end = DateTime(monday.year, monday.month, monday.day + 6, 23, 59, 59, 999);
} else {
start = DateTime(now.year, now.month, 1);
end = DateTime(now.year, now.month + 1, 0, 23, 59, 59, 999);
}
final fdc.QueryResult<
data_connect.ListShiftRolesByBusinessAndDatesSummaryData,
data_connect.ListShiftRolesByBusinessAndDatesSummaryVariables> result =
await _dataConnect
.listShiftRolesByBusinessAndDatesSummary(
businessId: businessId,
start: _toTimestamp(start),
end: _toTimestamp(end),
)
.execute();
final List<data_connect.ListShiftRolesByBusinessAndDatesSummaryShiftRoles>
shiftRoles = result.data.shiftRoles;
if (shiftRoles.isEmpty) {
return <InvoiceItem>[];
}
final Map<String, _RoleSummary> summary = <String, _RoleSummary>{};
for (final data_connect.ListShiftRolesByBusinessAndDatesSummaryShiftRoles role
in shiftRoles) {
final String roleId = role.roleId;
final String roleName = role.role.name;
final double hours = role.hours ?? 0.0;
final double totalValue = role.totalValue ?? 0.0;
final _RoleSummary? existing = summary[roleId];
if (existing == null) {
summary[roleId] = _RoleSummary(
roleId: roleId,
roleName: roleName,
totalHours: hours,
totalValue: totalValue,
);
} else {
summary[roleId] = existing.copyWith(
totalHours: existing.totalHours + hours,
totalValue: existing.totalValue + totalValue,
);
}
}
return summary.values
.map(
(_RoleSummary item) => InvoiceItem(
id: item.roleId,
invoiceId: item.roleId,
staffId: item.roleName,
workHours: item.totalHours,
rate: item.totalHours > 0 ? item.totalValue / item.totalHours : 0,
amount: item.totalValue,
),
)
.toList();
}
fdc.Timestamp _toTimestamp(DateTime dateTime) {
final int seconds = dateTime.millisecondsSinceEpoch ~/ 1000;
final int nanoseconds =
(dateTime.millisecondsSinceEpoch % 1000) * 1000000;
return fdc.Timestamp(nanoseconds, seconds);
}
}
class _RoleSummary {
const _RoleSummary({
required this.roleId,
required this.roleName,
required this.totalHours,
required this.totalValue,
});
final String roleId;
final String roleName;
final double totalHours;
final double totalValue;
_RoleSummary copyWith({
double? totalHours,
double? totalValue,
}) {
return _RoleSummary(
roleId: roleId,
roleName: roleName,
totalHours: totalHours ?? this.totalHours,
totalValue: totalValue ?? this.totalValue,
);
}
}

View File

@@ -0,0 +1,4 @@
enum BillingPeriod {
week,
month,
}

View File

@@ -1,4 +1,5 @@
import 'package:krow_domain/krow_domain.dart';
import '../models/billing_period.dart';
/// Repository interface for billing related operations.
///
@@ -19,5 +20,5 @@ abstract class BillingRepository {
Future<double> getSavingsAmount();
/// Fetches invoice items for spending breakdown analysis.
Future<List<InvoiceItem>> getSpendingBreakdown();
Future<List<InvoiceItem>> getSpendingBreakdown(BillingPeriod period);
}

View File

@@ -1,17 +1,20 @@
import 'package:krow_core/core.dart';
import 'package:krow_domain/krow_domain.dart';
import '../models/billing_period.dart';
import '../repositories/billing_repository.dart';
/// Use case for fetching the spending breakdown items.
///
/// This use case encapsulates the logic for retrieving the spending breakdown by category or item.
/// It delegates the data retrieval to the [BillingRepository].
class GetSpendingBreakdownUseCase extends NoInputUseCase<List<InvoiceItem>> {
class GetSpendingBreakdownUseCase
extends UseCase<BillingPeriod, List<InvoiceItem>> {
/// Creates a [GetSpendingBreakdownUseCase].
GetSpendingBreakdownUseCase(this._repository);
final BillingRepository _repository;
@override
Future<List<InvoiceItem>> call() => _repository.getSpendingBreakdown();
Future<List<InvoiceItem>> call(BillingPeriod period) =>
_repository.getSpendingBreakdown(period);
}

View File

@@ -1,5 +1,6 @@
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:krow_domain/krow_domain.dart';
import '../../domain/models/billing_period.dart';
import '../../domain/usecases/get_current_bill_amount.dart';
import '../../domain/usecases/get_invoice_history.dart';
import '../../domain/usecases/get_pending_invoices.dart';
@@ -26,6 +27,7 @@ class BillingBloc extends Bloc<BillingEvent, BillingState> {
_getSpendingBreakdown = getSpendingBreakdown,
super(const BillingState()) {
on<BillingLoadStarted>(_onLoadStarted);
on<BillingPeriodChanged>(_onPeriodChanged);
}
final GetCurrentBillAmountUseCase _getCurrentBillAmount;
@@ -45,7 +47,7 @@ class BillingBloc extends Bloc<BillingEvent, BillingState> {
_getSavingsAmount.call(),
_getPendingInvoices.call(),
_getInvoiceHistory.call(),
_getSpendingBreakdown.call(),
_getSpendingBreakdown.call(state.period),
]);
final double currentBill = results[0] as double;
@@ -83,6 +85,31 @@ class BillingBloc extends Bloc<BillingEvent, BillingState> {
}
}
Future<void> _onPeriodChanged(
BillingPeriodChanged event,
Emitter<BillingState> emit,
) async {
try {
final List<InvoiceItem> spendingItems =
await _getSpendingBreakdown.call(event.period);
final List<SpendingBreakdownItem> uiSpendingBreakdown =
_mapSpendingItemsToUiModel(spendingItems);
emit(
state.copyWith(
period: event.period,
spendingBreakdown: uiSpendingBreakdown,
),
);
} catch (e) {
emit(
state.copyWith(
status: BillingStatus.failure,
errorMessage: e.toString(),
),
);
}
}
BillingInvoice _mapInvoiceToUiModel(Invoice invoice) {
// In a real app, fetches related Event/Business names via ID.
// For now, mapping available fields and hardcoding missing UI placeholders.
@@ -104,16 +131,11 @@ class BillingBloc extends Bloc<BillingEvent, BillingState> {
List<SpendingBreakdownItem> _mapSpendingItemsToUiModel(
List<InvoiceItem> items,
) {
// Aggregating items by some logic.
// Since InvoiceItem doesn't have category, we mock it based on staffId or similar.
final Map<String, SpendingBreakdownItem> aggregation = <String, SpendingBreakdownItem>{};
final Map<String, SpendingBreakdownItem> aggregation =
<String, SpendingBreakdownItem>{};
for (final InvoiceItem item in items) {
// Mocking category derivation
final String category = item.staffId.hashCode % 2 == 0
? 'Server Staff'
: 'Bar Staff';
final String category = item.staffId;
final SpendingBreakdownItem? existing = aggregation[category];
if (existing != null) {
aggregation[category] = SpendingBreakdownItem(

View File

@@ -1,4 +1,5 @@
import 'package:equatable/equatable.dart';
import '../../domain/models/billing_period.dart';
/// Base class for all billing events.
abstract class BillingEvent extends Equatable {
@@ -14,3 +15,12 @@ class BillingLoadStarted extends BillingEvent {
/// Creates a [BillingLoadStarted] event.
const BillingLoadStarted();
}
class BillingPeriodChanged extends BillingEvent {
const BillingPeriodChanged(this.period);
final BillingPeriod period;
@override
List<Object?> get props => <Object?>[period];
}

View File

@@ -1,4 +1,5 @@
import 'package:equatable/equatable.dart';
import '../../domain/models/billing_period.dart';
import '../models/billing_invoice_model.dart';
import '../models/spending_breakdown_model.dart';
@@ -27,6 +28,7 @@ class BillingState extends Equatable {
this.pendingInvoices = const <BillingInvoice>[],
this.invoiceHistory = const <BillingInvoice>[],
this.spendingBreakdown = const <SpendingBreakdownItem>[],
this.period = BillingPeriod.week,
this.errorMessage,
});
@@ -48,6 +50,9 @@ class BillingState extends Equatable {
/// Breakdown of spending by category.
final List<SpendingBreakdownItem> spendingBreakdown;
/// Selected period for the breakdown.
final BillingPeriod period;
/// Error message if loading failed.
final String? errorMessage;
@@ -59,6 +64,7 @@ class BillingState extends Equatable {
List<BillingInvoice>? pendingInvoices,
List<BillingInvoice>? invoiceHistory,
List<SpendingBreakdownItem>? spendingBreakdown,
BillingPeriod? period,
String? errorMessage,
}) {
return BillingState(
@@ -68,6 +74,7 @@ class BillingState extends Equatable {
pendingInvoices: pendingInvoices ?? this.pendingInvoices,
invoiceHistory: invoiceHistory ?? this.invoiceHistory,
spendingBreakdown: spendingBreakdown ?? this.spendingBreakdown,
period: period ?? this.period,
errorMessage: errorMessage ?? this.errorMessage,
);
}
@@ -80,6 +87,7 @@ class BillingState extends Equatable {
pendingInvoices,
invoiceHistory,
spendingBreakdown,
period,
errorMessage,
];
}

View File

@@ -2,8 +2,10 @@ import 'package:core_localization/core_localization.dart';
import 'package:design_system/design_system.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import '../../domain/models/billing_period.dart';
import '../blocs/billing_bloc.dart';
import '../blocs/billing_state.dart';
import '../blocs/billing_event.dart';
import '../models/spending_breakdown_model.dart';
/// Card showing the spending breakdown for the current period.
@@ -92,6 +94,13 @@ class _SpendingBreakdownCardState extends State<SpendingBreakdownCard>
indicatorSize: TabBarIndicatorSize.tab,
labelPadding: const EdgeInsets.symmetric(horizontal: 12),
dividerColor: Colors.transparent,
onTap: (int index) {
final BillingPeriod period =
index == 0 ? BillingPeriod.week : BillingPeriod.month;
context.read<BillingBloc>().add(
BillingPeriodChanged(period),
);
},
tabs: <Widget>[
Tab(text: t.client_billing.week),
Tab(text: t.client_billing.month),

View File

@@ -435,3 +435,30 @@ query listShiftRolesByBusinessDateRangeCompletedOrders(
}
}
}
#view for billing period
query listShiftRolesByBusinessAndDatesSummary(
$businessId: UUID!
$start: Timestamp!
$end: Timestamp!
$offset: Int
$limit: Int
) @auth(level: USER) {
shiftRoles(
where: {
shift: {
date: { ge: $start, le: $end }
status: { eq: COMPLETED }
order: { businessId: { eq: $businessId } }
}
}
offset: $offset
limit: $limit
orderBy: { createdAt: DESC }
) {
roleId
hours
totalValue
role { id name }
}
}