zopassport 0.1.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 (110) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +407 -0
  3. package/app/.env.example +15 -0
  4. package/app/README.md +28 -0
  5. package/app/package.json +24 -0
  6. package/app/reanimated-mock.js +102 -0
  7. package/app/reanimated-mock.jsx +97 -0
  8. package/app/src/App.tsx +331 -0
  9. package/app/src/components/FounderBadge.tsx +26 -0
  10. package/app/src/components/OTPInput.tsx +149 -0
  11. package/app/src/components/PhoneInput.tsx +109 -0
  12. package/app/src/components/ZoAuth.tsx +320 -0
  13. package/app/src/components/ZoAvatar.tsx +87 -0
  14. package/app/src/components/ZoLanding.tsx +231 -0
  15. package/app/src/components/ZoOnboarding.tsx +524 -0
  16. package/app/src/components/ZoPassportCard.tsx +183 -0
  17. package/app/src/components/ZoProgressRing.tsx +57 -0
  18. package/app/src/components/index.ts +16 -0
  19. package/app/src/components/wallet/MovingShine.tsx +43 -0
  20. package/app/src/components/wallet/TransactionItem.tsx +84 -0
  21. package/app/src/components/wallet/TransactionList.tsx +65 -0
  22. package/app/src/components/wallet/WalletCard.tsx +152 -0
  23. package/app/src/components/wallet/WalletScreen.tsx +190 -0
  24. package/app/src/components/wallet/ZoToken.tsx +69 -0
  25. package/app/src/components/wallet/index.ts +8 -0
  26. package/app/src/components/wallet/styles/index.ts +4 -0
  27. package/app/src/components/wallet/styles/walletStyles.ts +210 -0
  28. package/app/src/sdk/ZoPassportSDK.ts +277 -0
  29. package/app/src/sdk/lib/api/auth.ts +223 -0
  30. package/app/src/sdk/lib/api/avatar.ts +155 -0
  31. package/app/src/sdk/lib/api/client.ts +135 -0
  32. package/app/src/sdk/lib/api/index.ts +8 -0
  33. package/app/src/sdk/lib/api/profile.ts +80 -0
  34. package/app/src/sdk/lib/api/wallet.ts +59 -0
  35. package/app/src/sdk/lib/types/auth.ts +78 -0
  36. package/app/src/sdk/lib/types/avatar.ts +22 -0
  37. package/app/src/sdk/lib/types/index.ts +8 -0
  38. package/app/src/sdk/lib/types/profile.ts +18 -0
  39. package/app/src/sdk/lib/types/wallet.ts +103 -0
  40. package/app/src/sdk/lib/types.ts +205 -0
  41. package/app/src/sdk/lib/utils/index.ts +6 -0
  42. package/app/src/sdk/lib/utils/phone.ts +71 -0
  43. package/app/src/sdk/lib/utils/storage.ts +116 -0
  44. package/app/src/sdk/lib/utils/wallet.ts +73 -0
  45. package/app/src/sdk/types.ts +205 -0
  46. package/app/src/styles.css +154 -0
  47. package/app/svg-mock.js +125 -0
  48. package/app/svg-mock.jsx +120 -0
  49. package/app/vite.config.ts +70 -0
  50. package/assets/ASSETS_MANIFEST.md +124 -0
  51. package/assets/bae.png +0 -0
  52. package/assets/bro.png +0 -0
  53. package/assets/cultural-stickers/Business.png +0 -0
  54. package/assets/cultural-stickers/Default (2).jpg +0 -0
  55. package/assets/cultural-stickers/Design.png +0 -0
  56. package/assets/cultural-stickers/FollowYourHeart.png +0 -0
  57. package/assets/cultural-stickers/Food.png +0 -0
  58. package/assets/cultural-stickers/Game.png +0 -0
  59. package/assets/cultural-stickers/Health&Fitness.png +0 -0
  60. package/assets/cultural-stickers/Home&Lifestyle.png +0 -0
  61. package/assets/cultural-stickers/Law.png +0 -0
  62. package/assets/cultural-stickers/Literature&Stories.png +0 -0
  63. package/assets/cultural-stickers/Music&Entertainment.png +0 -0
  64. package/assets/cultural-stickers/Nature&Wildlife.png +0 -0
  65. package/assets/cultural-stickers/Photography.png +0 -0
  66. package/assets/cultural-stickers/Science&Technology.png +0 -0
  67. package/assets/cultural-stickers/Spiritual.png +0 -0
  68. package/assets/cultural-stickers/Sport.png +0 -0
  69. package/assets/cultural-stickers/Stories&Journal.png +0 -0
  70. package/assets/cultural-stickers/Television&Cinema.png +0 -0
  71. package/assets/cultural-stickers/Travel&Adventure.png +0 -0
  72. package/assets/cultural-stickers/z.jpg (1).jpg +0 -0
  73. package/assets/figma-assets/landing-zo-logo.png +0 -0
  74. package/assets/images/rank1.jpeg +0 -0
  75. package/assets/index.ts +76 -0
  76. package/assets/lotties/loader.json +1216 -0
  77. package/assets/lotties/spinner.json +1 -0
  78. package/assets/videos/loading-screen-background.mp4 +0 -0
  79. package/assets/videos/opening-disks.mp4 +0 -0
  80. package/assets/wallet/constants.ts +38 -0
  81. package/assets/zo-coin.gif +0 -0
  82. package/assets/zo-fallback.png +0 -0
  83. package/dist/assets/index.d.mts +136 -0
  84. package/dist/assets/index.d.ts +136 -0
  85. package/dist/assets/index.js +133 -0
  86. package/dist/assets/index.js.map +1 -0
  87. package/dist/assets/index.mjs +100 -0
  88. package/dist/assets/index.mjs.map +1 -0
  89. package/dist/index.d.mts +789 -0
  90. package/dist/index.d.ts +789 -0
  91. package/dist/index.js +1118 -0
  92. package/dist/index.js.map +1 -0
  93. package/dist/index.mjs +1060 -0
  94. package/dist/index.mjs.map +1 -0
  95. package/dist/react-native.d.mts +537 -0
  96. package/dist/react-native.d.ts +537 -0
  97. package/dist/react-native.js +1617 -0
  98. package/dist/react-native.js.map +1 -0
  99. package/dist/react-native.mjs +1588 -0
  100. package/dist/react-native.mjs.map +1 -0
  101. package/dist/react.d.mts +824 -0
  102. package/dist/react.d.ts +824 -0
  103. package/dist/react.js +3856 -0
  104. package/dist/react.js.map +1 -0
  105. package/dist/react.mjs +3801 -0
  106. package/dist/react.mjs.map +1 -0
  107. package/package.json +112 -0
  108. package/scripts/init.js +196 -0
  109. package/scripts/postinstall.js +174 -0
  110. package/scripts/verify-build.js +121 -0
@@ -0,0 +1,205 @@
1
+ // src/lib/types.ts
2
+ // TypeScript types for Zo Passport SDK
3
+
4
+ // =====================
5
+ // User & Profile Types
6
+ // =====================
7
+
8
+ export interface ZoUser {
9
+ id: string;
10
+ first_name?: string;
11
+ last_name?: string;
12
+ bio?: string;
13
+ date_of_birth?: string;
14
+ place_name?: string;
15
+ body_type?: 'bro' | 'bae';
16
+ pfp_image?: string;
17
+ email_address?: string;
18
+ mobile_country_code?: string;
19
+ mobile_number?: string;
20
+ wallet_address?: string;
21
+ membership?: 'citizen' | 'founder';
22
+ cultures?: string[];
23
+ avatar?: {
24
+ status: 'pending' | 'processing' | 'completed' | 'failed';
25
+ image?: string;
26
+ };
27
+ role?: string;
28
+ created_at?: string;
29
+ updated_at?: string;
30
+ }
31
+
32
+ export interface ZoProfileResponse {
33
+ id: string;
34
+ first_name?: string;
35
+ last_name?: string;
36
+ bio?: string;
37
+ date_of_birth?: string;
38
+ location?: {
39
+ place_name?: string;
40
+ latitude?: number;
41
+ longitude?: number;
42
+ };
43
+ body_type?: 'bro' | 'bae';
44
+ pfp_image?: string;
45
+ email_address?: string;
46
+ mobile_country_code?: string;
47
+ mobile_number?: string;
48
+ wallet_address?: string;
49
+ zo_membership?: string;
50
+ cultures?: string[];
51
+ avatar?: {
52
+ status: 'pending' | 'processing' | 'completed' | 'failed';
53
+ image?: string;
54
+ };
55
+ founder_nfts?: any[];
56
+ founder_nfts_count?: number;
57
+ role?: string;
58
+ }
59
+
60
+ export interface ZoProfileUpdatePayload {
61
+ first_name?: string;
62
+ last_name?: string;
63
+ bio?: string;
64
+ date_of_birth?: string;
65
+ place_name?: string;
66
+ body_type?: 'bro' | 'bae';
67
+ pfp_image?: string;
68
+ cultures?: string[];
69
+ }
70
+
71
+ // =====================
72
+ // Auth Types
73
+ // =====================
74
+
75
+ export interface ZoAuthOTPRequest {
76
+ mobile_country_code: string;
77
+ mobile_number: string;
78
+ message_channel: string;
79
+ }
80
+
81
+ export interface ZoAuthOTPVerifyRequest {
82
+ mobile_country_code: string;
83
+ mobile_number: string;
84
+ otp: string;
85
+ }
86
+
87
+ export interface ZoAuthResponse {
88
+ user: ZoUser;
89
+ access_token: string;
90
+ refresh_token: string;
91
+ access_token_expiry: string;
92
+ refresh_token_expiry: string;
93
+ device_id?: string;
94
+ device_secret?: string;
95
+ }
96
+
97
+ export interface ZoTokenRefreshResponse {
98
+ access: string;
99
+ refresh: string;
100
+ access_expiry: string;
101
+ refresh_expiry: string;
102
+ }
103
+
104
+ // =====================
105
+ // Avatar Types
106
+ // =====================
107
+
108
+ export interface ZoAvatarGenerateRequest {
109
+ body_type: 'bro' | 'bae';
110
+ }
111
+
112
+ export interface ZoAvatarGenerateResponse {
113
+ task_id: string;
114
+ status: 'pending' | 'processing' | 'completed' | 'failed';
115
+ }
116
+
117
+ export interface ZoAvatarStatusResponse {
118
+ task_id: string;
119
+ status: 'pending' | 'processing' | 'completed' | 'failed';
120
+ result?: {
121
+ avatar_url?: string;
122
+ };
123
+ }
124
+
125
+ // =====================
126
+ // Booking Types
127
+ // =====================
128
+
129
+ export interface ZoBooking {
130
+ id: string;
131
+ property_name?: string;
132
+ check_in_datetime?: string;
133
+ check_out_datetime?: string;
134
+ booking_status?: string;
135
+ created_at?: string;
136
+ }
137
+
138
+ export interface ZoTrip {
139
+ id: string;
140
+ title?: string;
141
+ start_date?: string;
142
+ end_date?: string;
143
+ status?: string;
144
+ created_at?: string;
145
+ }
146
+
147
+ // =====================
148
+ // Error Types
149
+ // =====================
150
+
151
+ export interface ZoErrorResponse {
152
+ success?: boolean;
153
+ error?: string;
154
+ message?: string;
155
+ detail?: string;
156
+ errors?: string[];
157
+ }
158
+
159
+ // =====================
160
+ // Component Props Types
161
+ // =====================
162
+
163
+ export interface ZoPassportProfile {
164
+ avatar?: string;
165
+ name?: string;
166
+ isFounder?: boolean;
167
+ }
168
+
169
+ export interface ZoPassportCompletion {
170
+ done: number;
171
+ total: number;
172
+ }
173
+
174
+ // =====================
175
+ // Culture Types
176
+ // =====================
177
+
178
+ export const ZO_CULTURES = [
179
+ { id: 'travel', name: 'Travel & Adventure', icon: '/Cultural Stickers/Travel&Adventure.png' },
180
+ { id: 'design', name: 'Design', icon: '/Cultural Stickers/Design.png' },
181
+ { id: 'tech', name: 'Science & Technology', icon: '/Cultural Stickers/Science&Technology.png' },
182
+ { id: 'food', name: 'Food', icon: '/Cultural Stickers/Food.png' },
183
+ { id: 'music', name: 'Music & Entertainment', icon: '/Cultural Stickers/Music&Entertainment.png' },
184
+ { id: 'photography', name: 'Photography', icon: '/Cultural Stickers/Photography.png' },
185
+ { id: 'fitness', name: 'Health & Fitness', icon: '/Cultural Stickers/Health&Fitness.png' },
186
+ { id: 'sports', name: 'Sport', icon: '/Cultural Stickers/Sport.png' },
187
+ { id: 'literature', name: 'Literature & Stories', icon: '/Cultural Stickers/Literature&Stories.png' },
188
+ { id: 'cinema', name: 'Television & Cinema', icon: '/Cultural Stickers/Television&Cinema.png' },
189
+ { id: 'spiritual', name: 'Spiritual', icon: '/Cultural Stickers/Spiritual.png' },
190
+ { id: 'nature', name: 'Nature & Wildlife', icon: '/Cultural Stickers/Nature&Wildlife.png' },
191
+ { id: 'business', name: 'Business', icon: '/Cultural Stickers/Business.png' },
192
+ { id: 'law', name: 'Law', icon: '/Cultural Stickers/Law.png' },
193
+ { id: 'lifestyle', name: 'Home & Lifestyle', icon: '/Cultural Stickers/Home&Lifestyle.png' },
194
+ { id: 'gaming', name: 'Game', icon: '/Cultural Stickers/Game.png' },
195
+ { id: 'stories', name: 'Stories & Journal', icon: '/Cultural Stickers/Stories&Journal.png' },
196
+ ] as const;
197
+
198
+ export type ZoCultureId = typeof ZO_CULTURES[number]['id'];
199
+
200
+ // =====================
201
+ // Wallet Types
202
+ // =====================
203
+
204
+ export * from './types/wallet';
205
+
@@ -0,0 +1,6 @@
1
+ // src/lib/utils/index.ts
2
+ // Re-export all utilities
3
+
4
+ export * from './storage';
5
+ export * from './phone';
6
+
@@ -0,0 +1,71 @@
1
+ // src/lib/utils/phone.ts
2
+ // Phone number formatting utilities
3
+
4
+ export const COUNTRY_CODES = [
5
+ { code: '1', country: 'US', flag: '🇺🇸', name: 'United States' },
6
+ { code: '91', country: 'IN', flag: '🇮🇳', name: 'India' },
7
+ { code: '44', country: 'GB', flag: '🇬🇧', name: 'United Kingdom' },
8
+ { code: '86', country: 'CN', flag: '🇨🇳', name: 'China' },
9
+ { code: '81', country: 'JP', flag: '🇯🇵', name: 'Japan' },
10
+ { code: '82', country: 'KR', flag: '🇰🇷', name: 'South Korea' },
11
+ { code: '33', country: 'FR', flag: '🇫🇷', name: 'France' },
12
+ { code: '49', country: 'DE', flag: '🇩🇪', name: 'Germany' },
13
+ { code: '7', country: 'RU', flag: '🇷🇺', name: 'Russia' },
14
+ { code: '55', country: 'BR', flag: '🇧🇷', name: 'Brazil' },
15
+ { code: '61', country: 'AU', flag: '🇦🇺', name: 'Australia' },
16
+ { code: '65', country: 'SG', flag: '🇸🇬', name: 'Singapore' },
17
+ { code: '971', country: 'AE', flag: '🇦🇪', name: 'UAE' },
18
+ { code: '966', country: 'SA', flag: '🇸🇦', name: 'Saudi Arabia' },
19
+ { code: '62', country: 'ID', flag: '🇮🇩', name: 'Indonesia' },
20
+ { code: '60', country: 'MY', flag: '🇲🇾', name: 'Malaysia' },
21
+ { code: '66', country: 'TH', flag: '🇹🇭', name: 'Thailand' },
22
+ { code: '84', country: 'VN', flag: '🇻🇳', name: 'Vietnam' },
23
+ { code: '63', country: 'PH', flag: '🇵🇭', name: 'Philippines' },
24
+ { code: '31', country: 'NL', flag: '🇳🇱', name: 'Netherlands' },
25
+ ] as const;
26
+
27
+ /**
28
+ * Format phone number for display
29
+ * e.g., "5551234567" → "555-123-4567"
30
+ */
31
+ export function formatPhoneNumber(phone: string): string {
32
+ const cleaned = phone.replace(/\D/g, '');
33
+
34
+ if (cleaned.length === 10) {
35
+ return `${cleaned.slice(0, 3)}-${cleaned.slice(3, 6)}-${cleaned.slice(6)}`;
36
+ }
37
+
38
+ return cleaned;
39
+ }
40
+
41
+ /**
42
+ * Parse phone number to clean digits only
43
+ * Removes all non-digit characters
44
+ */
45
+ export function parsePhoneNumber(phone: string): string {
46
+ return phone.replace(/\D/g, '');
47
+ }
48
+
49
+ /**
50
+ * Validate phone number length
51
+ */
52
+ export function isValidPhoneNumber(phone: string, countryCode: string): boolean {
53
+ const cleaned = parsePhoneNumber(phone);
54
+
55
+ // Most countries use 10-digit numbers
56
+ // Some exceptions: UK (10-11), India (10), US (10)
57
+ if (countryCode === '91' || countryCode === '1') {
58
+ return cleaned.length === 10;
59
+ }
60
+
61
+ // General validation: 8-15 digits
62
+ return cleaned.length >= 8 && cleaned.length <= 15;
63
+ }
64
+
65
+ /**
66
+ * Get country by code
67
+ */
68
+ export function getCountryByCode(code: string) {
69
+ return COUNTRY_CODES.find(c => c.code === code);
70
+ }
71
+
@@ -0,0 +1,116 @@
1
+ // src/lib/utils/storage.ts
2
+ // Storage adapters for token persistence
3
+
4
+ /**
5
+ * Storage adapter interface
6
+ * Implement this to provide custom storage (e.g., AsyncStorage for React Native)
7
+ */
8
+ export interface StorageAdapter {
9
+ getItem(key: string): Promise<string | null>;
10
+ setItem(key: string, value: string): Promise<void>;
11
+ removeItem(key: string): Promise<void>;
12
+ }
13
+
14
+ /**
15
+ * Storage keys used by the SDK
16
+ */
17
+ export const STORAGE_KEYS = {
18
+ ACCESS_TOKEN: 'zo_access_token',
19
+ REFRESH_TOKEN: 'zo_refresh_token',
20
+ TOKEN_EXPIRY: 'zo_token_expiry',
21
+ REFRESH_EXPIRY: 'zo_refresh_expiry',
22
+ USER: 'zo_user',
23
+ CLIENT_DEVICE_ID: 'zo_device_id',
24
+ CLIENT_DEVICE_SECRET: 'zo_device_secret',
25
+ AVATAR_URL: 'zo_avatar_url',
26
+ NICKNAME: 'zo_nickname',
27
+ CITY: 'zo_city',
28
+ BODY_TYPE: 'zo_body_type',
29
+ } as const;
30
+
31
+ /**
32
+ * LocalStorage adapter for web browsers
33
+ */
34
+ export class LocalStorageAdapter implements StorageAdapter {
35
+ async getItem(key: string): Promise<string | null> {
36
+ if (typeof window === 'undefined') return null;
37
+ try {
38
+ return localStorage.getItem(key);
39
+ } catch {
40
+ return null;
41
+ }
42
+ }
43
+
44
+ async setItem(key: string, value: string): Promise<void> {
45
+ if (typeof window === 'undefined') return;
46
+ try {
47
+ localStorage.setItem(key, value);
48
+ } catch {
49
+ // Silently fail (storage full, private mode, etc.)
50
+ }
51
+ }
52
+
53
+ async removeItem(key: string): Promise<void> {
54
+ if (typeof window === 'undefined') return;
55
+ try {
56
+ localStorage.removeItem(key);
57
+ } catch {
58
+ // Silently fail
59
+ }
60
+ }
61
+ }
62
+
63
+ /**
64
+ * AsyncStorage adapter for React Native
65
+ * Provide AsyncStorage from @react-native-async-storage/async-storage
66
+ */
67
+ export class AsyncStorageAdapter implements StorageAdapter {
68
+ private storage: any;
69
+
70
+ constructor(asyncStorage: any) {
71
+ this.storage = asyncStorage;
72
+ }
73
+
74
+ async getItem(key: string): Promise<string | null> {
75
+ try {
76
+ return await this.storage.getItem(key);
77
+ } catch {
78
+ return null;
79
+ }
80
+ }
81
+
82
+ async setItem(key: string, value: string): Promise<void> {
83
+ try {
84
+ await this.storage.setItem(key, value);
85
+ } catch {
86
+ // Silently fail
87
+ }
88
+ }
89
+
90
+ async removeItem(key: string): Promise<void> {
91
+ try {
92
+ await this.storage.removeItem(key);
93
+ } catch {
94
+ // Silently fail
95
+ }
96
+ }
97
+ }
98
+
99
+ /**
100
+ * In-memory storage adapter (for SSR or testing)
101
+ */
102
+ export class MemoryStorageAdapter implements StorageAdapter {
103
+ private store: Map<string, string> = new Map();
104
+
105
+ async getItem(key: string): Promise<string | null> {
106
+ return this.store.get(key) || null;
107
+ }
108
+
109
+ async setItem(key: string, value: string): Promise<void> {
110
+ this.store.set(key, value);
111
+ }
112
+
113
+ async removeItem(key: string): Promise<void> {
114
+ this.store.delete(key);
115
+ }
116
+ }
@@ -0,0 +1,73 @@
1
+ // Wallet Formatting Utilities
2
+ // Framework-agnostic pure functions for wallet data formatting
3
+
4
+ /**
5
+ * Format balance number with commas
6
+ * @param balance - Raw balance number
7
+ * @returns Formatted string (e.g., "1,234.56")
8
+ */
9
+ export const formatBalance = (balance: number): string => {
10
+ if (balance === 0) return '0';
11
+
12
+ const formatted = balance.toLocaleString('en-US', {
13
+ minimumFractionDigits: 0,
14
+ maximumFractionDigits: 2,
15
+ });
16
+
17
+ return formatted;
18
+ };
19
+
20
+ /**
21
+ * Format balance for short display
22
+ * @param balance - Raw balance number
23
+ * @returns Shortened string (e.g., "1.2K", "1.5M")
24
+ */
25
+ export const formatBalanceShort = (balance: number): string => {
26
+ if (balance === 0) return '0';
27
+ if (balance < 1000) return formatBalance(balance);
28
+ if (balance < 1000000) return `${(balance / 1000).toFixed(1)}K`;
29
+ return `${(balance / 1000000).toFixed(1)}M`;
30
+ };
31
+
32
+ /**
33
+ * Format wallet address to short form
34
+ * @param address - Full wallet address
35
+ * @returns Shortened address (e.g., "0x12...34ab")
36
+ */
37
+ export const formatWalletAddress = (address: string): string => {
38
+ if (!address || address.length < 8) return address;
39
+ return `${address.slice(0, 4)}...${address.slice(-4)}`;
40
+ };
41
+
42
+ /**
43
+ * Format nickname with @ prefix
44
+ * @param nickname - User nickname
45
+ * @returns Formatted nickname (e.g., "@john")
46
+ */
47
+ export const formatNickname = (nickname: string): string => {
48
+ if (!nickname) return '';
49
+ return nickname.startsWith('@') ? nickname : `@${nickname}`;
50
+ };
51
+
52
+ /**
53
+ * Format transaction amount
54
+ * @param amount - Transaction amount
55
+ * @param action - deposit or spend
56
+ * @returns Formatted amount with +/- prefix
57
+ */
58
+ export const formatTransactionAmount = (
59
+ amount: number,
60
+ action: 'deposit' | 'spend'
61
+ ): string => {
62
+ const formatted = formatBalance(amount);
63
+ return action === 'spend' ? `- ${formatted}` : `+ ${formatted}`;
64
+ };
65
+
66
+ /**
67
+ * Get transaction color
68
+ * @param action - deposit or spend
69
+ * @returns Color hex code
70
+ */
71
+ export const getTransactionColor = (action: 'deposit' | 'spend'): string => {
72
+ return action === 'spend' ? '#FF4444' : '#00C853';
73
+ };
@@ -0,0 +1,205 @@
1
+ // src/lib/types.ts
2
+ // TypeScript types for Zo Passport SDK
3
+
4
+ // =====================
5
+ // User & Profile Types
6
+ // =====================
7
+
8
+ export interface ZoUser {
9
+ id: string;
10
+ first_name?: string;
11
+ last_name?: string;
12
+ bio?: string;
13
+ date_of_birth?: string;
14
+ place_name?: string;
15
+ body_type?: 'bro' | 'bae';
16
+ pfp_image?: string;
17
+ email_address?: string;
18
+ mobile_country_code?: string;
19
+ mobile_number?: string;
20
+ wallet_address?: string;
21
+ membership?: 'citizen' | 'founder';
22
+ cultures?: string[];
23
+ avatar?: {
24
+ status: 'pending' | 'processing' | 'completed' | 'failed';
25
+ image?: string;
26
+ };
27
+ role?: string;
28
+ created_at?: string;
29
+ updated_at?: string;
30
+ }
31
+
32
+ export interface ZoProfileResponse {
33
+ id: string;
34
+ first_name?: string;
35
+ last_name?: string;
36
+ bio?: string;
37
+ date_of_birth?: string;
38
+ location?: {
39
+ place_name?: string;
40
+ latitude?: number;
41
+ longitude?: number;
42
+ };
43
+ body_type?: 'bro' | 'bae';
44
+ pfp_image?: string;
45
+ email_address?: string;
46
+ mobile_country_code?: string;
47
+ mobile_number?: string;
48
+ wallet_address?: string;
49
+ zo_membership?: string;
50
+ cultures?: string[];
51
+ avatar?: {
52
+ status: 'pending' | 'processing' | 'completed' | 'failed';
53
+ image?: string;
54
+ };
55
+ founder_nfts?: any[];
56
+ founder_nfts_count?: number;
57
+ role?: string;
58
+ }
59
+
60
+ export interface ZoProfileUpdatePayload {
61
+ first_name?: string;
62
+ last_name?: string;
63
+ bio?: string;
64
+ date_of_birth?: string;
65
+ place_name?: string;
66
+ body_type?: 'bro' | 'bae';
67
+ pfp_image?: string;
68
+ cultures?: string[];
69
+ }
70
+
71
+ // =====================
72
+ // Auth Types
73
+ // =====================
74
+
75
+ export interface ZoAuthOTPRequest {
76
+ mobile_country_code: string;
77
+ mobile_number: string;
78
+ message_channel: string;
79
+ }
80
+
81
+ export interface ZoAuthOTPVerifyRequest {
82
+ mobile_country_code: string;
83
+ mobile_number: string;
84
+ otp: string;
85
+ }
86
+
87
+ export interface ZoAuthResponse {
88
+ user: ZoUser;
89
+ access_token: string;
90
+ refresh_token: string;
91
+ access_token_expiry: string;
92
+ refresh_token_expiry: string;
93
+ device_id?: string;
94
+ device_secret?: string;
95
+ }
96
+
97
+ export interface ZoTokenRefreshResponse {
98
+ access: string;
99
+ refresh: string;
100
+ access_expiry: string;
101
+ refresh_expiry: string;
102
+ }
103
+
104
+ // =====================
105
+ // Avatar Types
106
+ // =====================
107
+
108
+ export interface ZoAvatarGenerateRequest {
109
+ body_type: 'bro' | 'bae';
110
+ }
111
+
112
+ export interface ZoAvatarGenerateResponse {
113
+ task_id: string;
114
+ status: 'pending' | 'processing' | 'completed' | 'failed';
115
+ }
116
+
117
+ export interface ZoAvatarStatusResponse {
118
+ task_id: string;
119
+ status: 'pending' | 'processing' | 'completed' | 'failed';
120
+ result?: {
121
+ avatar_url?: string;
122
+ };
123
+ }
124
+
125
+ // =====================
126
+ // Booking Types
127
+ // =====================
128
+
129
+ export interface ZoBooking {
130
+ id: string;
131
+ property_name?: string;
132
+ check_in_datetime?: string;
133
+ check_out_datetime?: string;
134
+ booking_status?: string;
135
+ created_at?: string;
136
+ }
137
+
138
+ export interface ZoTrip {
139
+ id: string;
140
+ title?: string;
141
+ start_date?: string;
142
+ end_date?: string;
143
+ status?: string;
144
+ created_at?: string;
145
+ }
146
+
147
+ // =====================
148
+ // Error Types
149
+ // =====================
150
+
151
+ export interface ZoErrorResponse {
152
+ success?: boolean;
153
+ error?: string;
154
+ message?: string;
155
+ detail?: string;
156
+ errors?: string[];
157
+ }
158
+
159
+ // =====================
160
+ // Component Props Types
161
+ // =====================
162
+
163
+ export interface ZoPassportProfile {
164
+ avatar?: string;
165
+ name?: string;
166
+ isFounder?: boolean;
167
+ }
168
+
169
+ export interface ZoPassportCompletion {
170
+ done: number;
171
+ total: number;
172
+ }
173
+
174
+ // =====================
175
+ // Culture Types
176
+ // =====================
177
+
178
+ export const ZO_CULTURES = [
179
+ { id: 'travel', name: 'Travel & Adventure', icon: '/Cultural Stickers/Travel&Adventure.png' },
180
+ { id: 'design', name: 'Design', icon: '/Cultural Stickers/Design.png' },
181
+ { id: 'tech', name: 'Science & Technology', icon: '/Cultural Stickers/Science&Technology.png' },
182
+ { id: 'food', name: 'Food', icon: '/Cultural Stickers/Food.png' },
183
+ { id: 'music', name: 'Music & Entertainment', icon: '/Cultural Stickers/Music&Entertainment.png' },
184
+ { id: 'photography', name: 'Photography', icon: '/Cultural Stickers/Photography.png' },
185
+ { id: 'fitness', name: 'Health & Fitness', icon: '/Cultural Stickers/Health&Fitness.png' },
186
+ { id: 'sports', name: 'Sport', icon: '/Cultural Stickers/Sport.png' },
187
+ { id: 'literature', name: 'Literature & Stories', icon: '/Cultural Stickers/Literature&Stories.png' },
188
+ { id: 'cinema', name: 'Television & Cinema', icon: '/Cultural Stickers/Television&Cinema.png' },
189
+ { id: 'spiritual', name: 'Spiritual', icon: '/Cultural Stickers/Spiritual.png' },
190
+ { id: 'nature', name: 'Nature & Wildlife', icon: '/Cultural Stickers/Nature&Wildlife.png' },
191
+ { id: 'business', name: 'Business', icon: '/Cultural Stickers/Business.png' },
192
+ { id: 'law', name: 'Law', icon: '/Cultural Stickers/Law.png' },
193
+ { id: 'lifestyle', name: 'Home & Lifestyle', icon: '/Cultural Stickers/Home&Lifestyle.png' },
194
+ { id: 'gaming', name: 'Game', icon: '/Cultural Stickers/Game.png' },
195
+ { id: 'stories', name: 'Stories & Journal', icon: '/Cultural Stickers/Stories&Journal.png' },
196
+ ] as const;
197
+
198
+ export type ZoCultureId = typeof ZO_CULTURES[number]['id'];
199
+
200
+ // =====================
201
+ // Wallet Types
202
+ // =====================
203
+
204
+ export * from './types/wallet';
205
+