From 3fcbea8d60bef1fd9d232711187086bcc9452e7e Mon Sep 17 00:00:00 2001 From: Jamie Brunton Date: Thu, 1 Jan 2026 15:42:22 +0000 Subject: [PATCH] Update --- apps/admin/src/App.tsx | 9 + apps/admin/src/components/layout/Sidebar.tsx | 22 +- apps/admin/src/contexts/AuthContext.tsx | 2 + apps/admin/src/pages/users/UsersPage.tsx | 27 +- apps/mobile/android/app/build.gradle | 10 +- apps/mobile/android/app/google-services.json | 14 +- ...entry-295eb642e86589562852e8b2e825bdc0.hbc | Bin 0 -> 7659300 bytes .../assets/02bc1fa7c0313217bde2d65ccbff40c9 | Bin 0 -> 167 bytes .../assets/069d99eb1fa6712c0b9034a58c6b57dd | Bin 0 -> 483 bytes .../assets/0747a1317bbe9c6fc340b889ef8ab3ae | Bin 0 -> 332 bytes .../assets/0a328cd9c1afd0afe8e3b1ec5165b1b4 | Bin 0 -> 653 bytes .../assets/1190ab078c57159f4245a328118fcd9a | Bin 0 -> 201 bytes .../assets/140c53a7643ea949007aa9a282153849 | Bin 0 -> 13456 bytes .../assets/1681f34aaca71b8dfb70756bca331eb2 | Bin 0 -> 25788 bytes .../assets/19eeb73b9593a38f8e9f418337fc7d10 | Bin 0 -> 138 bytes .../assets/1f77739ca9ff2188b539c36f30ffa2be | Bin 0 -> 33736 bytes .../assets/20e71bdf79e3a97bf55fd9e164041578 | Bin 0 -> 4752 bytes .../assets/286d67d3f74808a60a78d3ebf1a5fb57 | Bin 0 -> 928 bytes .../assets/31b5ffea3daddc69dd01a1f3d6cf63c5 | Bin 0 -> 66200 bytes .../assets/35ba0eaec5a4f5ed12ca16fabeae451d | Bin 0 -> 207 bytes .../assets/370dd5af19f8364907b6e2c41f45dbbf | Bin 0 -> 67976 bytes .../assets/3a2ba31570920eeb9b1d217cabe58315 | Bin 0 -> 70344 bytes .../assets/3b89dd103490708d19a95adcae52210e | Bin 0 -> 134040 bytes .../assets/3cd68ccdb8938e3711da2e8831b85493 | Bin 0 -> 645 bytes .../assets/412dd9275b6b48ad28f5e3d81bb1f626 | Bin 0 -> 465 bytes .../assets/4403c6117ec30c859bc95d70ce4a71d3 | Bin 0 -> 258 bytes .../assets/4e85bc9ebe07e0340c9c4fc2f6c38908 | Bin 0 -> 356840 bytes .../assets/56c8d80832e37783f12c05db7c8849e2 | Bin 0 -> 209376 bytes .../assets/605ed7926cf39a2ad5ec2d1f9d391d3d | Bin 0 -> 202744 bytes .../assets/6148e7019854f3bde85b633cb88f3c25 | Bin 0 -> 442604 bytes .../assets/61ca7e64b7d605716c57706cef640b9a | Bin 0 -> 220 bytes .../assets/778ffc9fe8773a878e9c30a6304784de | Bin 0 -> 100 bytes .../assets/78c625386b4d0690b421eb0fc78f7b9c | Bin 0 -> 266 bytes .../assets/a76d309774d33d9856f650bed4292a23 | Bin 0 -> 56228 bytes .../assets/ab19f4cbc543357183a20571f68380a3 | Bin 0 -> 364 bytes .../assets/adec7d6f310bc577f05e8fe06a5daccf | Bin 0 -> 423676 bytes .../assets/aff2c65b39a296d4f7e96d0f58169170 | Bin 0 -> 334 bytes .../assets/b06871f281fee6b241d60582ae9369b9 | Bin 0 -> 165548 bytes .../assets/b49ae8ab2dbccb02c4d11caaacf09eab | Bin 0 -> 313528 bytes .../assets/b62641afc9ab487008e996a5c5865e56 | Bin 0 -> 1147844 bytes .../assets/c3273c9e5321f20d1e42c2efae2578c4 | Bin 0 -> 728 bytes .../assets/c79c3606a1cf168006ad3979763c7e0c | Bin 0 -> 134 bytes .../assets/cf3578021b5094cf7ab6322f2ee617a0 | Bin 0 -> 69577 bytes .../assets/d1ea1496f9057eb392d5bbf3732a61b7 | Bin 0 -> 469 bytes .../assets/d2285965fe34b05465047401b8595dd0 | Bin 0 -> 54056 bytes .../assets/d84e297c3b3e49a614248143d53e40ca | Bin 0 -> 141 bytes .../assets/d8b800c443b8972542883e0b9de2bdc6 | Bin 0 -> 188 bytes .../assets/d8e7601e3df962f83c62371ac14964d8 | Bin 0 -> 502 bytes .../assets/e20945d7c929279ef7a6f1db184a4470 | Bin 0 -> 56976 bytes .../assets/f7c53c47a66934504fcbc7cc164895a7 | Bin 0 -> 49404 bytes .../app/src/main/assets/index.android.bundle | 2238 +++++++++++++++++ .../android/app/src/main/assets/metadata.json | 1 + apps/mobile/app.json | 8 +- apps/mobile/app/(app)/_layout.tsx | 15 +- apps/mobile/app/(app)/onboarding.tsx | 2 +- apps/mobile/app/(app)/pairing.tsx | 4 +- apps/mobile/app/(app)/profile.tsx | 4 +- apps/mobile/app/(app)/swipe.tsx | 165 +- apps/mobile/app/(auth)/login.tsx | 1554 ++++++------ apps/mobile/app/_layout.tsx | 2 +- apps/mobile/app/index.tsx | 2 +- apps/mobile/package.json | 1 + .../src/components/SwipeCard.native.tsx | 235 +- apps/mobile/src/components/SwipeCard.web.tsx | 14 +- apps/mobile/src/lib/analytics.ts | 4 +- apps/mobile/src/types/supabase.ts | 60 +- apps/mobile/tsconfig.json | 3 +- package-lock.json | 17 + 68 files changed, 3579 insertions(+), 834 deletions(-) create mode 100644 apps/mobile/android/app/src/main/assets/_expo/static/js/android/entry-295eb642e86589562852e8b2e825bdc0.hbc create mode 100644 apps/mobile/android/app/src/main/assets/assets/02bc1fa7c0313217bde2d65ccbff40c9 create mode 100644 apps/mobile/android/app/src/main/assets/assets/069d99eb1fa6712c0b9034a58c6b57dd create mode 100644 apps/mobile/android/app/src/main/assets/assets/0747a1317bbe9c6fc340b889ef8ab3ae create mode 100644 apps/mobile/android/app/src/main/assets/assets/0a328cd9c1afd0afe8e3b1ec5165b1b4 create mode 100644 apps/mobile/android/app/src/main/assets/assets/1190ab078c57159f4245a328118fcd9a create mode 100644 apps/mobile/android/app/src/main/assets/assets/140c53a7643ea949007aa9a282153849 create mode 100644 apps/mobile/android/app/src/main/assets/assets/1681f34aaca71b8dfb70756bca331eb2 create mode 100644 apps/mobile/android/app/src/main/assets/assets/19eeb73b9593a38f8e9f418337fc7d10 create mode 100644 apps/mobile/android/app/src/main/assets/assets/1f77739ca9ff2188b539c36f30ffa2be create mode 100644 apps/mobile/android/app/src/main/assets/assets/20e71bdf79e3a97bf55fd9e164041578 create mode 100644 apps/mobile/android/app/src/main/assets/assets/286d67d3f74808a60a78d3ebf1a5fb57 create mode 100644 apps/mobile/android/app/src/main/assets/assets/31b5ffea3daddc69dd01a1f3d6cf63c5 create mode 100644 apps/mobile/android/app/src/main/assets/assets/35ba0eaec5a4f5ed12ca16fabeae451d create mode 100644 apps/mobile/android/app/src/main/assets/assets/370dd5af19f8364907b6e2c41f45dbbf create mode 100644 apps/mobile/android/app/src/main/assets/assets/3a2ba31570920eeb9b1d217cabe58315 create mode 100644 apps/mobile/android/app/src/main/assets/assets/3b89dd103490708d19a95adcae52210e create mode 100644 apps/mobile/android/app/src/main/assets/assets/3cd68ccdb8938e3711da2e8831b85493 create mode 100644 apps/mobile/android/app/src/main/assets/assets/412dd9275b6b48ad28f5e3d81bb1f626 create mode 100644 apps/mobile/android/app/src/main/assets/assets/4403c6117ec30c859bc95d70ce4a71d3 create mode 100644 apps/mobile/android/app/src/main/assets/assets/4e85bc9ebe07e0340c9c4fc2f6c38908 create mode 100644 apps/mobile/android/app/src/main/assets/assets/56c8d80832e37783f12c05db7c8849e2 create mode 100644 apps/mobile/android/app/src/main/assets/assets/605ed7926cf39a2ad5ec2d1f9d391d3d create mode 100644 apps/mobile/android/app/src/main/assets/assets/6148e7019854f3bde85b633cb88f3c25 create mode 100644 apps/mobile/android/app/src/main/assets/assets/61ca7e64b7d605716c57706cef640b9a create mode 100644 apps/mobile/android/app/src/main/assets/assets/778ffc9fe8773a878e9c30a6304784de create mode 100644 apps/mobile/android/app/src/main/assets/assets/78c625386b4d0690b421eb0fc78f7b9c create mode 100644 apps/mobile/android/app/src/main/assets/assets/a76d309774d33d9856f650bed4292a23 create mode 100644 apps/mobile/android/app/src/main/assets/assets/ab19f4cbc543357183a20571f68380a3 create mode 100644 apps/mobile/android/app/src/main/assets/assets/adec7d6f310bc577f05e8fe06a5daccf create mode 100644 apps/mobile/android/app/src/main/assets/assets/aff2c65b39a296d4f7e96d0f58169170 create mode 100644 apps/mobile/android/app/src/main/assets/assets/b06871f281fee6b241d60582ae9369b9 create mode 100644 apps/mobile/android/app/src/main/assets/assets/b49ae8ab2dbccb02c4d11caaacf09eab create mode 100644 apps/mobile/android/app/src/main/assets/assets/b62641afc9ab487008e996a5c5865e56 create mode 100644 apps/mobile/android/app/src/main/assets/assets/c3273c9e5321f20d1e42c2efae2578c4 create mode 100644 apps/mobile/android/app/src/main/assets/assets/c79c3606a1cf168006ad3979763c7e0c create mode 100644 apps/mobile/android/app/src/main/assets/assets/cf3578021b5094cf7ab6322f2ee617a0 create mode 100644 apps/mobile/android/app/src/main/assets/assets/d1ea1496f9057eb392d5bbf3732a61b7 create mode 100644 apps/mobile/android/app/src/main/assets/assets/d2285965fe34b05465047401b8595dd0 create mode 100644 apps/mobile/android/app/src/main/assets/assets/d84e297c3b3e49a614248143d53e40ca create mode 100644 apps/mobile/android/app/src/main/assets/assets/d8b800c443b8972542883e0b9de2bdc6 create mode 100644 apps/mobile/android/app/src/main/assets/assets/d8e7601e3df962f83c62371ac14964d8 create mode 100644 apps/mobile/android/app/src/main/assets/assets/e20945d7c929279ef7a6f1db184a4470 create mode 100644 apps/mobile/android/app/src/main/assets/assets/f7c53c47a66934504fcbc7cc164895a7 create mode 100644 apps/mobile/android/app/src/main/assets/index.android.bundle create mode 100644 apps/mobile/android/app/src/main/assets/metadata.json diff --git a/apps/admin/src/App.tsx b/apps/admin/src/App.tsx index a6d195d..dfea0bd 100755 --- a/apps/admin/src/App.tsx +++ b/apps/admin/src/App.tsx @@ -15,6 +15,7 @@ import { AdminsPage } from '@/pages/admins/AdminsPage'; import { RedemptionCodesPage } from '@/pages/RedemptionCodesPage'; import { FeedbackPage } from '@/pages/FeedbackPage'; import { UsageInsightsPage } from '@/pages/UsageInsightsPage'; +import { UserActivityPage } from '@/pages/activity/UserActivityPage'; import { AiSettingsPage } from '@/pages/AiSettingsPage'; import { AppSettingsPage } from '@/pages/AppSettingsPage'; @@ -96,6 +97,14 @@ function App() { } /> + + + + } + /> {/* System */} , + }, +]; + const contentNav: NavItem[] = [ { label: 'Categories', @@ -45,6 +55,12 @@ const usersNav: NavItem[] = [ icon: , requiredPermission: PERMISSION_KEYS.VIEW_USERS, }, + { + label: 'User Activity', + href: '/activity', + icon: , + requiredPermission: PERMISSION_KEYS.VIEW_ACTIVITY, + }, { label: 'Usage Insights', href: '/usage-insights', @@ -112,7 +128,9 @@ export function Sidebar({ mobileOpen, onMobileClose }: SidebarProps) { const NavLink = ({ item }: { item: NavItem }) => { if (item.requiredPermission && !hasPermission(item.requiredPermission)) return null; - const isActive = location.pathname.startsWith(item.href); + const isActive = item.href === '/' + ? location.pathname === '/' + : location.pathname.startsWith(item.href); return ( + @@ -310,6 +329,7 @@ export function Sidebar({ mobileOpen, onMobileClose }: SidebarProps) { {/* Navigation */}
+ diff --git a/apps/admin/src/contexts/AuthContext.tsx b/apps/admin/src/contexts/AuthContext.tsx index b88ed78..656ff68 100644 --- a/apps/admin/src/contexts/AuthContext.tsx +++ b/apps/admin/src/contexts/AuthContext.tsx @@ -18,6 +18,7 @@ export const PERMISSION_KEYS = { VIEW_MEDIA: 'view_media', VIEW_MATCHES: 'view_matches', VIEW_RESPONSES: 'view_responses', + VIEW_ACTIVITY: 'view_activity', // System permissions MANAGE_CODES: 'manage_codes', MANAGE_ADMINS: 'manage_admins', @@ -38,6 +39,7 @@ export const PERMISSION_METADATA: Record { setLoading(true); try { - // Fetch profiles + // Fetch profiles with auth info (includes last_sign_in_at) const { data: profilesData, error } = await supabase - .from('profiles') - .select('*') - .order('created_at', { ascending: false }); + .rpc('get_profiles_with_auth_info'); if (error) throw error; @@ -197,13 +197,14 @@ export function UsersPage() { Couple Storage Joined + Last Active {filteredProfiles.length === 0 ? ( - + {search ? 'No users found matching your search.' : 'No users yet.'} @@ -224,7 +225,14 @@ export function UsersPage() { - {profile.email || '—'} +
+ {profile.email || '—'} + {profile.email && !profile.email_confirmed_at && ( + + + + )} +
{profile.is_premium ? ( @@ -268,6 +276,11 @@ export function UsersPage() { ? format(new Date(profile.created_at), 'MMM d, yyyy') : '—'} + + {profile.last_sign_in_at + ? format(new Date(profile.last_sign_in_at), 'MMM d, yyyy h:mm a') + : 'Never'} +