Improve invitation UI and fix access removal

- Move role selector (Caretaker/Guardian) above email input in Access screen
- Remove "(view only)" suffix from Caretaker role in email templates
- Remove "expires in 7 days" text from invitation emails
- Remove expires_at field from invitation creation (invitations never expire)
- Fix deletion of accepted invitations (now also removes user_access record)
- Add favicon to accept-invite.html page
This commit is contained in:
Sergei 2026-01-04 10:28:36 -08:00
parent d9fcdf1751
commit f4ff281bcc
4 changed files with 37 additions and 39 deletions

View File

@ -324,32 +324,7 @@ export default function ShareAccessScreen() {
<View style={styles.section}>
<Text style={styles.sectionTitle}>Invite Someone</Text>
<View style={styles.inputRow}>
<TextInput
style={styles.input}
placeholder="Email address"
placeholderTextColor={AppColors.textMuted}
value={email}
onChangeText={setEmail}
autoCapitalize="none"
autoCorrect={false}
keyboardType="email-address"
editable={!isLoading}
/>
<TouchableOpacity
style={[styles.sendButton, isLoading && styles.sendButtonDisabled]}
onPress={handleSendInvite}
disabled={isLoading}
>
{isLoading ? (
<ActivityIndicator size="small" color={AppColors.white} />
) : (
<Ionicons name="send" size={18} color={AppColors.white} />
)}
</TouchableOpacity>
</View>
{/* Role Toggle */}
{/* Role Toggle - above email */}
<View style={styles.roleToggle}>
<TouchableOpacity
style={[styles.roleButton, role === 'caretaker' && styles.roleButtonActive]}
@ -374,6 +349,31 @@ export default function ShareAccessScreen() {
? 'Can view activity and chat with Julia'
: 'Full access: edit info, manage subscription'}
</Text>
<View style={[styles.inputRow, { marginTop: Spacing.md }]}>
<TextInput
style={styles.input}
placeholder="Email address"
placeholderTextColor={AppColors.textMuted}
value={email}
onChangeText={setEmail}
autoCapitalize="none"
autoCorrect={false}
keyboardType="email-address"
editable={!isLoading}
/>
<TouchableOpacity
style={[styles.sendButton, isLoading && styles.sendButtonDisabled]}
onPress={handleSendInvite}
disabled={isLoading}
>
{isLoading ? (
<ActivityIndicator size="small" color={AppColors.white} />
) : (
<Ionicons name="send" size={18} color={AppColors.white} />
)}
</TouchableOpacity>
</View>
</View>
{/* People with Access */}

View File

@ -310,9 +310,7 @@ router.post('/', async (req, res) => {
attempts++;
}
// Create invitation (expires in 7 days)
const expiresAt = new Date(Date.now() + 7 * 24 * 60 * 60 * 1000);
// Create invitation (no expiry)
const { data: invitation, error } = await supabase
.from('invitations')
.insert({
@ -321,8 +319,7 @@ router.post('/', async (req, res) => {
token: inviteToken,
role: role,
email: email?.toLowerCase() || null,
label: label || null,
expires_at: expiresAt.toISOString()
label: label || null
})
.select()
.single();
@ -690,8 +687,13 @@ router.delete('/:id', async (req, res) => {
return res.status(404).json({ error: 'Invitation not found' });
}
if (invitation.accepted_at) {
return res.status(400).json({ error: 'Cannot revoke accepted invitation' });
// If invitation was accepted, also remove user_access
if (invitation.accepted_by) {
await supabase
.from('user_access')
.delete()
.eq('beneficiary_id', invitation.beneficiary_id)
.eq('accessor_id', invitation.accepted_by);
}
// Delete invitation

View File

@ -222,7 +222,7 @@ If you didn't request this code, you can safely ignore this email.
async function sendInvitationEmail({ email, inviterName, beneficiaryName, role, inviteCode }) {
const frontendUrl = process.env.FRONTEND_URL || 'https://wellnuo.smartlaunchhub.com';
const acceptLink = `${frontendUrl}/accept-invite.html?code=${inviteCode}`;
const roleText = role === 'guardian' ? 'Guardian (full access)' : 'Caretaker (view only)';
const roleText = role === 'guardian' ? 'Guardian' : 'Caretaker';
const htmlContent = `
<!DOCTYPE html>
@ -276,9 +276,6 @@ async function sendInvitationEmail({ email, inviterName, beneficiaryName, role,
</tr>
</table>
<p style="margin: 24px 0 0 0; font-size: 13px; color: #999999; text-align: center;">
This invitation expires in 7 days.
</p>
</td>
</tr>
@ -310,8 +307,6 @@ Your invitation code: ${inviteCode}
Accept your invitation: ${acceptLink}
This invitation expires in 7 days.
If you didn't expect this invitation, you can safely ignore this email.
WellNuo - Elderly Care Monitoring

View File

@ -4,6 +4,7 @@
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Accept Invitation - WellNuo</title>
<link rel="icon" type="image/png" href="/favicon.png">
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body {