Add per-user notification time preferences

Allow users to customize when they receive notification reminders:
- Add hour fields to NotificationPreference model
- Add timezone conversion utilities (localHourToUtc, utcHourToLocal)
- Add time picker UI for iOS (wheel picker in sheet)
- Add time picker UI for Android (hour chip selector dialog)
- Times stored in UTC, displayed in user's local timezone
- Add localized strings for time picker UI

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Trey t
2025-12-07 00:25:38 -06:00
parent 83e2cd14a6
commit 9d6e7c4f2a
10 changed files with 1086 additions and 7 deletions
+54
View File
@@ -332,6 +332,9 @@
"Are you sure you want to cancel this task? This action cannot be undone." : {
"comment" : "An alert message displayed when a user taps the \"Cancel Task\" button in the task details view. It confirms that the user intends to cancel the task and warns them that the action cannot be undone.",
"isCommentAutoGenerated" : true
},
"Are you sure you want to remove %@ from this residence?" : {
},
"At least 8 characters" : {
@@ -4270,6 +4273,10 @@
},
"CASERA PRO" : {
},
"Change" : {
"comment" : "A button that allows the user to change the time in a notification.",
"isCommentAutoGenerated" : true
},
"Check Your Email" : {
"comment" : "A heading that instructs the user to check their email for a verification code.",
@@ -17324,6 +17331,10 @@
"comment" : "A button label that says \"Generate\".",
"isCommentAutoGenerated" : true
},
"Hour" : {
"comment" : "A picker for selecting an hour.",
"isCommentAutoGenerated" : true
},
"I have a code to join" : {
"comment" : "A button label that instructs the user to join an existing Casera account.",
"isCommentAutoGenerated" : true
@@ -17415,6 +17426,9 @@
},
"No properties yet" : {
},
"No shared users" : {
},
"No tasks yet" : {
"comment" : "A description displayed when a user has no tasks.",
@@ -17428,6 +17442,18 @@
"comment" : "A message displayed when no task templates match a search query.",
"isCommentAutoGenerated" : true
},
"Notification Time" : {
"comment" : "The title of the sheet where a user can select the time for receiving notifications.",
"isCommentAutoGenerated" : true
},
"Notifications will be sent at %@ in your local timezone" : {
"comment" : "A label below the time picker, explaining that the notifications will be sent at the selected time in the user's local timezone.",
"isCommentAutoGenerated" : true
},
"Notify at %@" : {
"comment" : "A row in the checkout view that lets the user change the time they want to be notified.",
"isCommentAutoGenerated" : true
},
"OK" : {
"comment" : "A button that dismisses the success dialog.",
"isCommentAutoGenerated" : true
@@ -21302,6 +21328,12 @@
},
"Re-enter new password" : {
},
"Remove" : {
},
"Remove User" : {
},
"Reset Password" : {
"comment" : "The title of the screen where users can reset their passwords.",
@@ -24456,6 +24488,10 @@
},
"Return to Login" : {
},
"Save" : {
"comment" : "The text for a button that saves the selected time.",
"isCommentAutoGenerated" : true
},
"Save your home to your account" : {
@@ -24464,6 +24500,10 @@
"comment" : "A placeholder text for a search bar in the task templates browser.",
"isCommentAutoGenerated" : true
},
"Select Notification Time" : {
"comment" : "A label displayed above the picker for selecting the notification time.",
"isCommentAutoGenerated" : true
},
"Send New Code" : {
"comment" : "A button label that allows a user to request a new verification code.",
"isCommentAutoGenerated" : true
@@ -24472,6 +24512,10 @@
"comment" : "A button label that says \"Send Reset Code\".",
"isCommentAutoGenerated" : true
},
"Set Custom Time" : {
"comment" : "A button that allows a user to set a custom notification time.",
"isCommentAutoGenerated" : true
},
"Set New Password" : {
},
@@ -24616,6 +24660,9 @@
"Share this code with others to give them access to %@" : {
"comment" : "A caption below the share code, explaining that it can be shared with others to give them access to a residence. The argument is the name of the residence.",
"isCommentAutoGenerated" : true
},
"Shared Users (%lld)" : {
},
"Signing in with Apple..." : {
@@ -29650,6 +29697,13 @@
"comment" : "A description of the benefit of upgrading to the Pro plan.",
"isCommentAutoGenerated" : true
},
"Users with access to this residence. Use the share button to invite others." : {
},
"Using system default time" : {
"comment" : "A description of how a user can set a custom notification time.",
"isCommentAutoGenerated" : true
},
"Verification Code" : {
"comment" : "A label displayed above the text field for entering a verification code.",
"isCommentAutoGenerated" : true