@digilogiclabs/create-saas-app 1.5.4 → 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/CHANGELOG.md +109 -49
  2. package/bin/index.js +1 -1
  3. package/dist/.tsbuildinfo +1 -1
  4. package/dist/templates/mobile/base/template/App.tsx +113 -23
  5. package/dist/templates/mobile/base/template/package.json +5 -2
  6. package/dist/templates/web/base/template/package.json +1 -1
  7. package/dist/templates/web/base/template/src/app/checkout/page.tsx +99 -8
  8. package/dist/templates/web/base/template/src/app/dashboard/page.tsx +309 -0
  9. package/dist/templates/web/base/template/src/app/globals.css +97 -0
  10. package/dist/templates/web/base/template/src/app/login/page.tsx +36 -8
  11. package/dist/templates/web/base/template/src/app/page.tsx +123 -83
  12. package/dist/templates/web/base/template/src/app/signup/page.tsx +36 -8
  13. package/dist/templates/web/base/template/src/components/shared/header.tsx +49 -30
  14. package/dist/templates/web/ui-auth/template/package.json +2 -2
  15. package/dist/templates/web/ui-auth/template/src/app/page.tsx +203 -61
  16. package/dist/templates/web/ui-auth-payments/template/package.json +2 -2
  17. package/dist/templates/web/ui-auth-payments/template/src/app/checkout/page.tsx +253 -87
  18. package/dist/templates/web/ui-auth-payments/template/src/app/globals.css +129 -0
  19. package/dist/templates/web/ui-auth-payments/template/src/app/page.tsx +246 -74
  20. package/dist/templates/web/ui-auth-payments/template/src/components/shared/header.tsx +106 -40
  21. package/dist/templates/web/ui-auth-payments-audio/template/package.json +2 -2
  22. package/dist/templates/web/ui-auth-payments-audio/template/src/app/page.tsx +221 -82
  23. package/dist/templates/web/ui-auth-payments-audio/template/src/components/shared/header.tsx +132 -40
  24. package/dist/templates/web/ui-auth-payments-video/template/package.json +2 -2
  25. package/dist/templates/web/ui-auth-payments-video/template/src/app/globals.css +146 -0
  26. package/dist/templates/web/ui-auth-payments-video/template/src/app/page.tsx +259 -85
  27. package/dist/templates/web/ui-auth-payments-video/template/src/components/shared/header.tsx +133 -41
  28. package/package.json +106 -106
  29. package/src/templates/mobile/base/template/App.tsx +113 -23
  30. package/src/templates/mobile/base/template/package.json +5 -2
  31. package/src/templates/web/base/template/package.json +1 -1
  32. package/src/templates/web/base/template/src/app/checkout/page.tsx +99 -8
  33. package/src/templates/web/base/template/src/app/dashboard/page.tsx +309 -0
  34. package/src/templates/web/base/template/src/app/globals.css +97 -0
  35. package/src/templates/web/base/template/src/app/login/page.tsx +36 -8
  36. package/src/templates/web/base/template/src/app/page.tsx +123 -83
  37. package/src/templates/web/base/template/src/app/signup/page.tsx +36 -8
  38. package/src/templates/web/base/template/src/components/shared/header.tsx +49 -30
  39. package/src/templates/web/ui-auth/template/package.json +2 -2
  40. package/src/templates/web/ui-auth/template/src/app/page.tsx +203 -61
  41. package/src/templates/web/ui-auth-payments/template/package.json +2 -2
  42. package/src/templates/web/ui-auth-payments/template/src/app/checkout/page.tsx +253 -87
  43. package/src/templates/web/ui-auth-payments/template/src/app/globals.css +129 -0
  44. package/src/templates/web/ui-auth-payments/template/src/app/page.tsx +246 -74
  45. package/src/templates/web/ui-auth-payments/template/src/components/shared/header.tsx +106 -40
  46. package/src/templates/web/ui-auth-payments-audio/template/package.json +2 -2
  47. package/src/templates/web/ui-auth-payments-audio/template/src/app/page.tsx +221 -82
  48. package/src/templates/web/ui-auth-payments-audio/template/src/components/shared/header.tsx +132 -40
  49. package/src/templates/web/ui-auth-payments-video/template/package.json +2 -2
  50. package/src/templates/web/ui-auth-payments-video/template/src/app/globals.css +146 -0
  51. package/src/templates/web/ui-auth-payments-video/template/src/app/page.tsx +259 -85
  52. package/src/templates/web/ui-auth-payments-video/template/src/components/shared/header.tsx +133 -41
  53. package/dist/index.js +0 -1173
  54. package/dist/index.js.map +0 -1
@@ -5,35 +5,92 @@ import { SafeAreaProvider } from 'react-native-safe-area-context';
5
5
  import { AuthProvider, useAuth } from '@digilogiclabs/saas-factory-auth/native';
6
6
  import { StripeProvider } from '@digilogiclabs/saas-factory-payments/native';
7
7
  import { Link, Slot } from 'expo-router';
8
+ import {
9
+ NativePageTransition as PageTransition,
10
+ NativeMobileHero as MobileHero,
11
+ NativeMobileContainer as MobileContainer,
12
+ NativeNetworkAwareContent as NetworkAwareContent,
13
+ NativeOfflineWrapper as OfflineWrapper,
14
+ useNetworkInfo,
15
+ useOfflineState
16
+ } from '@digilogiclabs/saas-factory-ui/native';
8
17
 
9
18
  function AppContent() {
10
19
  const { user, signOut } = useAuth();
20
+ const networkInfo = useNetworkInfo();
21
+ const isOnline = useOfflineState();
11
22
 
12
23
  return (
13
- <View style={styles.container}>
14
- {user ? (
15
- <>
16
- <Text style={styles.title}>Welcome back!</Text>
17
- <Text style={styles.subtitle}>You are signed in.</Text>
18
- <Link href="/checkout" style={styles.link}>
19
- <Text>Checkout</Text>
20
- </Link>
21
- <Button title="Sign Out" onPress={signOut} />
22
- </>
23
- ) : (
24
- <>
25
- <Text style={styles.title}>Welcome to {{titleCaseName}}</Text>
26
- <Text style={styles.subtitle}>{{description}}</Text>
27
- <Link href="/login" style={styles.link}>
28
- <Text>Login</Text>
29
- </Link>
30
- <Link href="/signup" style={styles.link}>
31
- <Text>Sign Up</Text>
32
- </Link>
33
- </>
34
- )}
24
+ <PageTransition type="fade" duration={300}>
25
+ <OfflineWrapper
26
+ cacheStrategy="stale-while-revalidate"
27
+ showOfflineIndicator={true}
28
+ >
29
+ <MobileContainer style={styles.container}>
30
+ <NetworkAwareContent
31
+ showOnOffline={
32
+ <View style={styles.offlineContainer}>
33
+ <Text style={styles.offlineTitle}>You're offline</Text>
34
+ <Text style={styles.offlineText}>
35
+ Some features may be limited while offline.
36
+ </Text>
37
+ </View>
38
+ }
39
+ >
40
+ {user ? (
41
+ <MobileHero
42
+ title={{
43
+ text: "Welcome back!",
44
+ size: "lg"
45
+ }}
46
+ description="You are signed in and ready to go."
47
+ actions={[
48
+ {
49
+ label: "Go to Checkout",
50
+ href: "/checkout",
51
+ variant: "default"
52
+ },
53
+ {
54
+ label: "Sign Out",
55
+ onPress: signOut,
56
+ variant: "outline"
57
+ }
58
+ ]}
59
+ />
60
+ ) : (
61
+ <MobileHero
62
+ title={{
63
+ text: "Welcome to {{titleCaseName}}",
64
+ size: "xl"
65
+ }}
66
+ description="{{description}}"
67
+ actions={[
68
+ {
69
+ label: "Get Started",
70
+ href: "/signup",
71
+ variant: "default"
72
+ },
73
+ {
74
+ label: "Sign In",
75
+ href: "/login",
76
+ variant: "outline"
77
+ }
78
+ ]}
79
+ />
80
+ )}
81
+
82
+ {/* Network Status Indicator */}
83
+ <View style={styles.statusContainer}>
84
+ <Text style={styles.statusText}>
85
+ Status: {isOnline ? '🟢 Online' : '🔴 Offline'}
86
+ {networkInfo?.type && ` • ${networkInfo.type}`}
87
+ </Text>
88
+ </View>
89
+ </NetworkAwareContent>
90
+ </MobileContainer>
91
+ </OfflineWrapper>
35
92
  <StatusBar style="auto" />
36
- </View>
93
+ </PageTransition>
37
94
  );
38
95
  }
39
96
 
@@ -85,4 +142,37 @@ const styles = StyleSheet.create({
85
142
  textAlign: 'center',
86
143
  width: '80%',
87
144
  },
145
+ offlineContainer: {
146
+ padding: 20,
147
+ alignItems: 'center',
148
+ backgroundColor: '#fff3cd',
149
+ borderRadius: 8,
150
+ margin: 20,
151
+ },
152
+ offlineTitle: {
153
+ fontSize: 18,
154
+ fontWeight: 'bold',
155
+ color: '#856404',
156
+ marginBottom: 8,
157
+ },
158
+ offlineText: {
159
+ fontSize: 14,
160
+ color: '#856404',
161
+ textAlign: 'center',
162
+ },
163
+ statusContainer: {
164
+ position: 'absolute',
165
+ bottom: 50,
166
+ left: 0,
167
+ right: 0,
168
+ alignItems: 'center',
169
+ },
170
+ statusText: {
171
+ fontSize: 12,
172
+ color: '#666',
173
+ backgroundColor: 'rgba(255, 255, 255, 0.9)',
174
+ paddingHorizontal: 12,
175
+ paddingVertical: 6,
176
+ borderRadius: 20,
177
+ },
88
178
  });
@@ -22,11 +22,14 @@
22
22
  "react-native-screens": "~3.22.0",
23
23
  "react-native-safe-area-context": "4.6.3",
24
24
  "react-native-gesture-handler": "~2.12.0",
25
- "@digilogiclabs/saas-factory-ui": "^0.7.2",
25
+ "@digilogiclabs/saas-factory-ui": "^0.13.0",
26
26
  "@digilogiclabs/saas-factory-auth": "^0.4.3",
27
27
  "@digilogiclabs/saas-factory-payments": "^0.2.0",
28
28
  "firebase": "^10.0.0",
29
- "@supabase/supabase-js": "^2.0.0"
29
+ "@supabase/supabase-js": "^2.0.0",
30
+ "@react-native-community/netinfo": "^11.0.0",
31
+ "@react-native-async-storage/async-storage": "^1.19.0",
32
+ "expo-haptics": "~12.4.0"
30
33
  },
31
34
  "devDependencies": {
32
35
  "@babel/core": "^7.20.0",
@@ -17,7 +17,7 @@
17
17
  "next": "^15.0.0",
18
18
  "react": "^19.0.0",
19
19
  "react-dom": "^19.0.0",
20
- "@digilogiclabs/saas-factory-ui": "^0.7.2",
20
+ "@digilogiclabs/saas-factory-ui": "^0.13.0",
21
21
  "@digilogiclabs/saas-factory-auth": "^0.4.3",
22
22
  "@digilogiclabs/saas-factory-payments": "^0.2.0",
23
23
  "tailwindcss": "^3.3.0",
@@ -3,9 +3,20 @@
3
3
  import React from 'react';
4
4
  import { useStripe } from '@digilogiclabs/saas-factory-payments';
5
5
  import { Button } from '@/components/ui/button';
6
+ import {
7
+ PageTransition,
8
+ MobileContainer,
9
+ TouchInput,
10
+ MobileForm,
11
+ SwipeableCard,
12
+ NetworkAwareContent,
13
+ useNetworkInfo
14
+ } from '@digilogiclabs/saas-factory-ui';
15
+ import { CreditCard, Zap } from 'lucide-react';
6
16
 
7
17
  export default function CheckoutPage() {
8
18
  const { handleCheckout } = useStripe();
19
+ const networkInfo = useNetworkInfo();
9
20
 
10
21
  const onCheckout = async () => {
11
22
  await handleCheckout({
@@ -15,14 +26,94 @@ export default function CheckoutPage() {
15
26
  };
16
27
 
17
28
  return (
18
- <div className="flex items-center justify-center min-h-screen bg-gray-100">
19
- <div className="p-8 bg-white rounded-lg shadow-md">
20
- <h1 className="text-2xl font-bold mb-4">Checkout</h1>
21
- <p className="mb-6">Click the button below to proceed to payment.</p>
22
- <Button onClick={onCheckout}>
23
- Proceed to Checkout
24
- </Button>
29
+ <PageTransition type="slide" direction="up" duration={350}>
30
+ <div className="flex items-center justify-center min-h-screen bg-gray-100">
31
+ <MobileContainer className="w-full max-w-md">
32
+ <NetworkAwareContent
33
+ showOnSlow={
34
+ <div className="p-6 bg-white rounded-lg shadow-md">
35
+ <div className="flex items-center gap-2 mb-4">
36
+ <CreditCard className="h-6 w-6 text-blue-600" />
37
+ <h1 className="text-xl font-bold">Checkout</h1>
38
+ </div>
39
+ <p className="mb-6 text-gray-600">
40
+ Simplified checkout for slower connections.
41
+ </p>
42
+ <Button
43
+ onClick={onCheckout}
44
+ className="w-full"
45
+ size="lg"
46
+ >
47
+ Proceed to Checkout
48
+ </Button>
49
+ </div>
50
+ }
51
+ >
52
+ <SwipeableCard
53
+ leftActions={[
54
+ {
55
+ id: 'back',
56
+ label: 'Back',
57
+ onAction: () => window.history.back(),
58
+ color: 'gray'
59
+ }
60
+ ]}
61
+ rightActions={[
62
+ {
63
+ id: 'proceed',
64
+ label: 'Pay Now',
65
+ onAction: onCheckout,
66
+ color: 'green'
67
+ }
68
+ ]}
69
+ threshold={60}
70
+ hapticFeedback={true}
71
+ showActionLabels={true}
72
+ >
73
+ <div className="p-8 bg-white rounded-lg shadow-md">
74
+ <div className="flex items-center gap-3 mb-6">
75
+ <div className="p-3 bg-blue-100 rounded-full">
76
+ <Zap className="h-6 w-6 text-blue-600" />
77
+ </div>
78
+ <div>
79
+ <h1 className="text-2xl font-bold">Premium Checkout</h1>
80
+ <p className="text-sm text-gray-500">
81
+ {networkInfo?.effectiveType && `${networkInfo.effectiveType.toUpperCase()} connection`}
82
+ </p>
83
+ </div>
84
+ </div>
85
+
86
+ <div className="space-y-4 mb-6">
87
+ <div className="p-4 bg-blue-50 rounded-lg">
88
+ <h3 className="font-semibold text-blue-900">Pro Plan</h3>
89
+ <p className="text-blue-700">$29/month • All features included</p>
90
+ </div>
91
+
92
+ <div className="text-sm text-gray-600">
93
+ <p>✓ Touch-optimized checkout experience</p>
94
+ <p>✓ Network-aware performance</p>
95
+ <p>✓ Secure payment processing</p>
96
+ </div>
97
+ </div>
98
+
99
+ <div className="space-y-3">
100
+ <Button
101
+ onClick={onCheckout}
102
+ className="w-full"
103
+ size="lg"
104
+ >
105
+ Proceed to Checkout
106
+ </Button>
107
+
108
+ <p className="text-xs text-center text-gray-500">
109
+ Swipe left to go back • Swipe right to pay now
110
+ </p>
111
+ </div>
112
+ </div>
113
+ </SwipeableCard>
114
+ </NetworkAwareContent>
115
+ </MobileContainer>
25
116
  </div>
26
- </div>
117
+ </PageTransition>
27
118
  );
28
119
  }
@@ -0,0 +1,309 @@
1
+ 'use client';
2
+
3
+ import React, { useState } from 'react';
4
+ import { useAuth } from '@digilogiclabs/saas-factory-auth';
5
+ import { Button } from '@/components/ui/button';
6
+ import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
7
+ import {
8
+ PageTransition,
9
+ MobileContainer,
10
+ ResponsiveGrid,
11
+ PullToRefresh,
12
+ LazyImage,
13
+ VirtualScrollList,
14
+ SwipeableCard,
15
+ NetworkAwareContent,
16
+ OfflineWrapper,
17
+ useNetworkInfo,
18
+ useOfflineState
19
+ } from '@digilogiclabs/saas-factory-ui';
20
+ import {
21
+ BarChart3,
22
+ Users,
23
+ DollarSign,
24
+ TrendingUp,
25
+ Settings,
26
+ Archive,
27
+ Star,
28
+ Trash2,
29
+ Wifi,
30
+ WifiOff
31
+ } from 'lucide-react';
32
+
33
+ // Mock data for demonstration
34
+ const mockActivityData = Array.from({ length: 50 }, (_, i) => ({
35
+ id: i + 1,
36
+ title: `Activity ${i + 1}`,
37
+ description: `This is a sample activity item #${i + 1}`,
38
+ timestamp: new Date(Date.now() - Math.random() * 7 * 24 * 60 * 60 * 1000).toISOString(),
39
+ type: ['user', 'sale', 'system'][Math.floor(Math.random() * 3)],
40
+ avatar: `https://api.dicebear.com/7.x/avataaars/svg?seed=${i}`
41
+ }));
42
+
43
+ export default function DashboardPage() {
44
+ const { user } = useAuth();
45
+ const networkInfo = useNetworkInfo();
46
+ const isOnline = useOfflineState();
47
+ const [activityData, setActivityData] = useState(mockActivityData);
48
+ const [isRefreshing, setIsRefreshing] = useState(false);
49
+
50
+ const handleRefresh = async () => {
51
+ setIsRefreshing(true);
52
+ // Simulate API call
53
+ await new Promise(resolve => setTimeout(resolve, 1500));
54
+ setIsRefreshing(false);
55
+ };
56
+
57
+ const handleArchive = (id: number) => {
58
+ setActivityData(prev => prev.filter(item => item.id !== id));
59
+ };
60
+
61
+ const handleStar = (id: number) => {
62
+ console.log('Starred item:', id);
63
+ };
64
+
65
+ const handleDelete = (id: number) => {
66
+ setActivityData(prev => prev.filter(item => item.id !== id));
67
+ };
68
+
69
+ const stats = [
70
+ {
71
+ title: 'Total Users',
72
+ value: '2,543',
73
+ change: '+12%',
74
+ icon: Users,
75
+ color: 'blue'
76
+ },
77
+ {
78
+ title: 'Revenue',
79
+ value: '$12,456',
80
+ change: '+8%',
81
+ icon: DollarSign,
82
+ color: 'green'
83
+ },
84
+ {
85
+ title: 'Growth',
86
+ value: '23.5%',
87
+ change: '+2.1%',
88
+ icon: TrendingUp,
89
+ color: 'purple'
90
+ },
91
+ {
92
+ title: 'Analytics',
93
+ value: '1,234',
94
+ change: '+5%',
95
+ icon: BarChart3,
96
+ color: 'orange'
97
+ }
98
+ ];
99
+
100
+ return (
101
+ <PageTransition type="slide" direction="horizontal" duration={300}>
102
+ <OfflineWrapper
103
+ cacheStrategy="stale-while-revalidate"
104
+ showOfflineIndicator={true}
105
+ backgroundSync={true}
106
+ >
107
+ <PullToRefresh
108
+ onRefresh={handleRefresh}
109
+ threshold={80}
110
+ loadingIndicator="spinner"
111
+ hapticOnTrigger={true}
112
+ networkAware={true}
113
+ >
114
+ <div className="min-h-screen bg-gray-50">
115
+ <MobileContainer className="py-6">
116
+ {/* Header */}
117
+ <div className="mb-6">
118
+ <div className="flex items-center justify-between">
119
+ <div>
120
+ <h1 className="text-2xl font-bold text-gray-900">
121
+ Welcome back, {user?.email?.split('@')[0]}
122
+ </h1>
123
+ <p className="text-gray-600 flex items-center gap-2">
124
+ {isOnline ? (
125
+ <>
126
+ <Wifi className="h-4 w-4 text-green-600" />
127
+ <span>Online</span>
128
+ </>
129
+ ) : (
130
+ <>
131
+ <WifiOff className="h-4 w-4 text-red-600" />
132
+ <span>Offline</span>
133
+ </>
134
+ )}
135
+ {networkInfo?.effectiveType && (
136
+ <span className="text-xs bg-gray-200 px-2 py-1 rounded">
137
+ {networkInfo.effectiveType.toUpperCase()}
138
+ </span>
139
+ )}
140
+ </p>
141
+ </div>
142
+ <Button variant="outline" size="icon">
143
+ <Settings className="h-4 w-4" />
144
+ </Button>
145
+ </div>
146
+ </div>
147
+
148
+ {/* Stats Grid */}
149
+ <NetworkAwareContent
150
+ showOnSlow={
151
+ <ResponsiveGrid columns={{ base: 2, md: 2 }} gap="sm" className="mb-6">
152
+ {stats.slice(0, 2).map((stat, index) => (
153
+ <Card key={index}>
154
+ <CardContent className="p-4">
155
+ <div className="flex items-center gap-2">
156
+ <stat.icon className={`h-5 w-5 text-${stat.color}-600`} />
157
+ <div>
158
+ <p className="text-sm font-medium text-gray-600">{stat.title}</p>
159
+ <p className="text-lg font-bold">{stat.value}</p>
160
+ </div>
161
+ </div>
162
+ </CardContent>
163
+ </Card>
164
+ ))}
165
+ </ResponsiveGrid>
166
+ }
167
+ >
168
+ <ResponsiveGrid columns={{ base: 2, md: 4 }} gap="md" className="mb-6">
169
+ {stats.map((stat, index) => (
170
+ <Card key={index}>
171
+ <CardContent className="p-4">
172
+ <div className="flex items-center justify-between mb-2">
173
+ <stat.icon className={`h-5 w-5 text-${stat.color}-600`} />
174
+ <span className="text-sm text-green-600 font-medium">
175
+ {stat.change}
176
+ </span>
177
+ </div>
178
+ <div>
179
+ <p className="text-sm font-medium text-gray-600">{stat.title}</p>
180
+ <p className="text-2xl font-bold">{stat.value}</p>
181
+ </div>
182
+ </CardContent>
183
+ </Card>
184
+ ))}
185
+ </ResponsiveGrid>
186
+ </NetworkAwareContent>
187
+
188
+ {/* Activity Feed */}
189
+ <Card className="mb-6">
190
+ <CardHeader>
191
+ <CardTitle className="flex items-center gap-2">
192
+ <BarChart3 className="h-5 w-5" />
193
+ Recent Activity
194
+ </CardTitle>
195
+ <CardDescription>
196
+ Swipe left on items to archive or star them
197
+ </CardDescription>
198
+ </CardHeader>
199
+ <CardContent className="p-0">
200
+ <VirtualScrollList
201
+ items={activityData}
202
+ itemHeight={80}
203
+ containerHeight={400}
204
+ bufferSize={5}
205
+ renderItem={(item) => (
206
+ <SwipeableCard
207
+ key={item.id}
208
+ leftActions={[
209
+ {
210
+ id: 'archive',
211
+ label: 'Archive',
212
+ onAction: () => handleArchive(item.id),
213
+ color: 'blue',
214
+ icon: Archive
215
+ },
216
+ {
217
+ id: 'star',
218
+ label: 'Star',
219
+ onAction: () => handleStar(item.id),
220
+ color: 'yellow',
221
+ icon: Star
222
+ }
223
+ ]}
224
+ rightActions={[
225
+ {
226
+ id: 'delete',
227
+ label: 'Delete',
228
+ onAction: () => handleDelete(item.id),
229
+ color: 'red',
230
+ icon: Trash2
231
+ }
232
+ ]}
233
+ threshold={50}
234
+ hapticFeedback={true}
235
+ showActionLabels={true}
236
+ >
237
+ <div className="flex items-center gap-3 p-4 border-b">
238
+ <LazyImage
239
+ src={item.avatar}
240
+ alt={`Activity ${item.id}`}
241
+ className="w-10 h-10 rounded-full"
242
+ placeholder="skeleton"
243
+ webpSupport={true}
244
+ mobileOptimization={{
245
+ quality: 80,
246
+ format: "webp"
247
+ }}
248
+ />
249
+ <div className="flex-1 min-w-0">
250
+ <h4 className="font-medium text-gray-900 truncate">
251
+ {item.title}
252
+ </h4>
253
+ <p className="text-sm text-gray-600 truncate">
254
+ {item.description}
255
+ </p>
256
+ <p className="text-xs text-gray-400">
257
+ {new Date(item.timestamp).toLocaleDateString()}
258
+ </p>
259
+ </div>
260
+ <div className={`px-2 py-1 rounded-full text-xs ${
261
+ item.type === 'user' ? 'bg-blue-100 text-blue-800' :
262
+ item.type === 'sale' ? 'bg-green-100 text-green-800' :
263
+ 'bg-gray-100 text-gray-800'
264
+ }`}>
265
+ {item.type}
266
+ </div>
267
+ </div>
268
+ </SwipeableCard>
269
+ )}
270
+ onEndReached={() => {
271
+ console.log('Loading more items...');
272
+ }}
273
+ mobileOptimized={true}
274
+ />
275
+ </CardContent>
276
+ </Card>
277
+
278
+ {/* Quick Actions */}
279
+ <Card>
280
+ <CardHeader>
281
+ <CardTitle>Quick Actions</CardTitle>
282
+ <CardDescription>
283
+ Common tasks and shortcuts
284
+ </CardDescription>
285
+ </CardHeader>
286
+ <CardContent>
287
+ <ResponsiveGrid columns={{ base: 2, md: 3 }} gap="sm">
288
+ <Button variant="outline" className="h-20 flex flex-col gap-2">
289
+ <Users className="h-5 w-5" />
290
+ <span className="text-xs">Manage Users</span>
291
+ </Button>
292
+ <Button variant="outline" className="h-20 flex flex-col gap-2">
293
+ <DollarSign className="h-5 w-5" />
294
+ <span className="text-xs">View Revenue</span>
295
+ </Button>
296
+ <Button variant="outline" className="h-20 flex flex-col gap-2">
297
+ <BarChart3 className="h-5 w-5" />
298
+ <span className="text-xs">Analytics</span>
299
+ </Button>
300
+ </ResponsiveGrid>
301
+ </CardContent>
302
+ </Card>
303
+ </MobileContainer>
304
+ </div>
305
+ </PullToRefresh>
306
+ </OfflineWrapper>
307
+ </PageTransition>
308
+ );
309
+ }