Client and server responsibilities
My Dairy is a salary and overtime management project with attendance, custom salary periods, Google authentication, PHP/MySQL APIs, report export and server-controlled application behavior. Because the dashboard, history and salary calculations depend on the same records, a small mismatch in user identity or date logic can make correct database data appear missing in the app. When I work on client and server responsibilities, I first decide which layer owns the responsibility. Flutter should handle presentation and interaction, while protected business decisions are checked by the server or platform configuration that actually controls them. This separation prevents a UI workaround from hiding a backend or release problem.
I deliberately test failure paths for client and server responsibilities. Network timeout, empty data, invalid input, cancelled authentication, unavailable advertising, or a rejected API request should result in a controlled screen state. The application should not show an endless loader or silently save incomplete information simply because the successful path was the only one tested.
Validating login input
For validating login input, I capture the exact state before editing code: input values, user identifier, date range, HTTP status or native error, raw response where safe, and whether the failure happens in debug, locally signed release, or a build installed from Google Play. That evidence usually narrows the problem much faster than changing several files at once.
Another important check is consistency. If the backend calculates a salary period one way but a Flutter history screen sends another month range, both pieces of code may be individually valid while the user sees the wrong result. I therefore compare the parameters and business rules end to end before changing the visual layer.
$stmt = $conn->prepare(
'SELECT id,name,email,password_hash FROM users WHERE email=? LIMIT 1'
);
$stmt->bind_param('s', $email);
$stmt->execute();Prepared database queries
I deliberately test failure paths for prepared database queries. Network timeout, empty data, invalid input, cancelled authentication, unavailable advertising, or a rejected API request should result in a controlled screen state. The application should not show an endless loader or silently save incomplete information simply because the successful path was the only one tested.
After a fix, I repeat the original failing workflow rather than accepting a successful compilation as proof. For Play-specific behavior I test the Play-delivered artifact; for API problems I verify the real production endpoint; and for data problems I compare the returned JSON with the model used by the screen.
Password verification
Another important check is consistency. If the backend calculates a salary period one way but a Flutter history screen sends another month range, both pieces of code may be individually valid while the user sees the wrong result. I therefore compare the parameters and business rules end to end before changing the visual layer.
My Dairy is a salary and overtime management project with attendance, custom salary periods, Google authentication, PHP/MySQL APIs, report export and server-controlled application behavior. Because the dashboard, history and salary calculations depend on the same records, a small mismatch in user identity or date logic can make correct database data appear missing in the app. When I work on password verification, I first decide which layer owns the responsibility. Flutter should handle presentation and interaction, while protected business decisions are checked by the server or platform configuration that actually controls them. This separation prevents a UI workaround from hiding a backend or release problem.
Flutter response handling
After a fix, I repeat the original failing workflow rather than accepting a successful compilation as proof. For Play-specific behavior I test the Play-delivered artifact; for API problems I verify the real production endpoint; and for data problems I compare the returned JSON with the model used by the screen.
For flutter response handling, I capture the exact state before editing code: input values, user identifier, date range, HTTP status or native error, raw response where safe, and whether the failure happens in debug, locally signed release, or a build installed from Google Play. That evidence usually narrows the problem much faster than changing several files at once.
Authorization after login
My Dairy is a salary and overtime management project with attendance, custom salary periods, Google authentication, PHP/MySQL APIs, report export and server-controlled application behavior. Because the dashboard, history and salary calculations depend on the same records, a small mismatch in user identity or date logic can make correct database data appear missing in the app. When I work on authorization after login, I first decide which layer owns the responsibility. Flutter should handle presentation and interaction, while protected business decisions are checked by the server or platform configuration that actually controls them. This separation prevents a UI workaround from hiding a backend or release problem.
I deliberately test failure paths for authorization after login. Network timeout, empty data, invalid input, cancelled authentication, unavailable advertising, or a rejected API request should result in a controlled screen state. The application should not show an endless loader or silently save incomplete information simply because the successful path was the only one tested.
My troubleshooting workflow
Another important check is consistency. If the backend calculates a salary period one way but a Flutter history screen sends another month range, both pieces of code may be individually valid while the user sees the wrong result. I therefore compare the parameters and business rules end to end before changing the visual layer.
After a fix, I repeat the original failing workflow rather than accepting a successful compilation as proof. For Play-specific behavior I test the Play-delivered artifact; for API problems I verify the real production endpoint; and for data problems I compare the returned JSON with the model used by the screen.
What this project taught me
The main lesson from My Dairy is that production behavior depends on more than Dart code. Signing certificates, package names, API endpoints, database filters, SDK configuration and store settings are all part of the application. I keep those values in a release checklist and verify the distribution that users will actually install.