@codingfactory/socialkit-vue 0.5.3 → 0.7.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.
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -1
- package/dist/services/gamification.d.ts +87 -0
- package/dist/services/gamification.d.ts.map +1 -0
- package/dist/services/gamification.js +263 -0
- package/dist/services/gamification.js.map +1 -0
- package/dist/stores/content.d.ts +1418 -0
- package/dist/stores/content.d.ts.map +1 -0
- package/dist/stores/content.js +1195 -0
- package/dist/stores/content.js.map +1 -0
- package/dist/stores/gamification.d.ts +2875 -0
- package/dist/stores/gamification.d.ts.map +1 -0
- package/dist/stores/gamification.js +1136 -0
- package/dist/stores/gamification.js.map +1 -0
- package/dist/types/api.d.ts +1 -0
- package/dist/types/api.d.ts.map +1 -1
- package/dist/types/content-api.d.ts +23 -0
- package/dist/types/content-api.d.ts.map +1 -0
- package/dist/types/content-api.js +5 -0
- package/dist/types/content-api.js.map +1 -0
- package/dist/types/content.d.ts +309 -0
- package/dist/types/content.d.ts.map +1 -0
- package/dist/types/content.js +36 -0
- package/dist/types/content.js.map +1 -0
- package/dist/types/gamification.d.ts +267 -0
- package/dist/types/gamification.d.ts.map +1 -0
- package/dist/types/gamification.js +5 -0
- package/dist/types/gamification.js.map +1 -0
- package/dist/types/media.d.ts +63 -0
- package/dist/types/media.d.ts.map +1 -0
- package/dist/types/media.js +13 -0
- package/dist/types/media.js.map +1 -0
- package/dist/types/reputation.d.ts +55 -0
- package/dist/types/reputation.d.ts.map +1 -0
- package/dist/types/reputation.js +5 -0
- package/dist/types/reputation.js.map +1 -0
- package/package.json +1 -1
- package/src/index.ts +143 -0
- package/src/services/gamification.ts +432 -0
- package/src/stores/content.ts +1477 -0
- package/src/stores/gamification.ts +1565 -0
- package/src/types/api.ts +1 -0
- package/src/types/content-api.ts +24 -0
- package/src/types/content.ts +381 -0
- package/src/types/gamification.ts +286 -0
- package/src/types/media.ts +81 -0
- package/src/types/reputation.ts +78 -0
package/src/types/api.ts
CHANGED
|
@@ -51,6 +51,7 @@ export interface RequestConfig {
|
|
|
51
51
|
headers?: Record<string, string>
|
|
52
52
|
params?: Record<string, string | number | boolean>
|
|
53
53
|
timeout?: number
|
|
54
|
+
responseType?: 'arraybuffer' | 'blob' | 'document' | 'json' | 'text'
|
|
54
55
|
onUploadProgress?: (progressEvent: UploadProgressEvent) => void
|
|
55
56
|
signal?: AbortSignal
|
|
56
57
|
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Content API type definitions.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import type { FeedEntry, Post } from './content.js'
|
|
6
|
+
|
|
7
|
+
export interface FeedResponse {
|
|
8
|
+
data: {
|
|
9
|
+
entries: FeedEntry[]
|
|
10
|
+
meta?: {
|
|
11
|
+
next_cursor?: string | null
|
|
12
|
+
has_more?: boolean
|
|
13
|
+
current_page?: number
|
|
14
|
+
total?: number
|
|
15
|
+
}
|
|
16
|
+
next_cursor?: string | null
|
|
17
|
+
}
|
|
18
|
+
page_entries?: FeedEntry[]
|
|
19
|
+
next_cursor?: string | null
|
|
20
|
+
entries?: FeedEntry[]
|
|
21
|
+
posts?: Post[]
|
|
22
|
+
hasMore?: boolean
|
|
23
|
+
nextCursor?: string | null
|
|
24
|
+
}
|
|
@@ -0,0 +1,381 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Content-domain types and store contracts shared across SocialKit frontends.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import type { ApiService } from '../services/api.js'
|
|
6
|
+
import type { LocalMediaItem } from './media.js'
|
|
7
|
+
|
|
8
|
+
export interface BaseEntity {
|
|
9
|
+
id: string
|
|
10
|
+
created_at: string
|
|
11
|
+
updated_at?: string
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export type VideoRenderStatus = 'pending' | 'processing' | 'ready' | 'failed'
|
|
15
|
+
|
|
16
|
+
export interface PostMedia {
|
|
17
|
+
id?: string
|
|
18
|
+
uuid?: string
|
|
19
|
+
mime_type?: string
|
|
20
|
+
url?: string
|
|
21
|
+
thumb_url?: string
|
|
22
|
+
preview_url?: string
|
|
23
|
+
playback_url?: string
|
|
24
|
+
thumbnail_url?: string
|
|
25
|
+
urls?: {
|
|
26
|
+
original?: string
|
|
27
|
+
thumb?: string
|
|
28
|
+
thumbnail?: string
|
|
29
|
+
preview?: string
|
|
30
|
+
}
|
|
31
|
+
type?: 'image' | 'video'
|
|
32
|
+
alt_text?: string
|
|
33
|
+
width?: number
|
|
34
|
+
height?: number
|
|
35
|
+
responsive?: {
|
|
36
|
+
preview?: {
|
|
37
|
+
srcset?: string
|
|
38
|
+
}
|
|
39
|
+
original?: {
|
|
40
|
+
srcset?: string
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
processing_status?: VideoRenderStatus
|
|
44
|
+
video_render_status?: VideoRenderStatus
|
|
45
|
+
video_render_progress?: number
|
|
46
|
+
video_render_error?: string | null
|
|
47
|
+
video_render_job_id?: string | null
|
|
48
|
+
source_media_id?: string
|
|
49
|
+
output_media_id?: string
|
|
50
|
+
provider?: string
|
|
51
|
+
provider_asset_id?: string
|
|
52
|
+
provider_library_id?: string
|
|
53
|
+
duration?: number
|
|
54
|
+
aspect_ratio?: string
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export interface PostAuthor {
|
|
58
|
+
id: string
|
|
59
|
+
name: string
|
|
60
|
+
avatar?: string | null
|
|
61
|
+
username?: string | null
|
|
62
|
+
handle?: string | null
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export type PostFeelingType = 'mood' | 'activity'
|
|
66
|
+
export type PostFeelingValue =
|
|
67
|
+
| 'inspired'
|
|
68
|
+
| 'creative'
|
|
69
|
+
| 'focused'
|
|
70
|
+
| 'relaxed'
|
|
71
|
+
| 'excited'
|
|
72
|
+
| 'grateful'
|
|
73
|
+
| 'proud'
|
|
74
|
+
| 'experimental'
|
|
75
|
+
| 'in_the_studio'
|
|
76
|
+
| 'teaching_a_class'
|
|
77
|
+
| 'at_a_show'
|
|
78
|
+
| 'experimenting'
|
|
79
|
+
| 'collaborating'
|
|
80
|
+
| 'learning_a_technique'
|
|
81
|
+
|
|
82
|
+
export interface PostFeeling {
|
|
83
|
+
type: PostFeelingType
|
|
84
|
+
value: PostFeelingValue
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export interface PostMeta {
|
|
88
|
+
live_viewers?: number | null
|
|
89
|
+
feeling?: PostFeeling | null
|
|
90
|
+
[key: string]: unknown
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export type PostShareType = 'original' | 'repost' | 'quote'
|
|
94
|
+
|
|
95
|
+
export interface QuotedPostPreview {
|
|
96
|
+
id: string
|
|
97
|
+
body: string
|
|
98
|
+
author?: PostAuthor | null
|
|
99
|
+
author_id?: string
|
|
100
|
+
created_at?: string
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export interface Post extends BaseEntity {
|
|
104
|
+
body: string
|
|
105
|
+
share_type?: PostShareType
|
|
106
|
+
quoted_post_id?: string | null
|
|
107
|
+
quoted_post?: QuotedPostPreview | null
|
|
108
|
+
content_warning?: string | null
|
|
109
|
+
sensitive?: boolean
|
|
110
|
+
author: PostAuthor
|
|
111
|
+
author_id: string
|
|
112
|
+
reactions_count: number
|
|
113
|
+
comments_count: number
|
|
114
|
+
user_has_reacted: boolean
|
|
115
|
+
user_has_reposted?: boolean
|
|
116
|
+
user_repost_id?: string | null
|
|
117
|
+
visibility?: 'public' | 'private' | 'friends'
|
|
118
|
+
media?: PostMedia[]
|
|
119
|
+
meta?: PostMeta
|
|
120
|
+
live_viewers?: number | null
|
|
121
|
+
is_quarantined?: boolean
|
|
122
|
+
published_site_names?: string[] | null
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
export interface PostWithPendingState extends Post {
|
|
126
|
+
_isPending?: boolean
|
|
127
|
+
_tempId?: string
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
export interface Comment extends BaseEntity {
|
|
131
|
+
body: string
|
|
132
|
+
post_id: string
|
|
133
|
+
author: PostAuthor
|
|
134
|
+
media?: PostMedia[]
|
|
135
|
+
parent_id?: string
|
|
136
|
+
thread_id?: string
|
|
137
|
+
depth?: number
|
|
138
|
+
reactions_count?: number
|
|
139
|
+
replies_count?: number
|
|
140
|
+
user_has_reacted?: boolean
|
|
141
|
+
user_reaction_type?: string
|
|
142
|
+
reactions?: Record<string, number>
|
|
143
|
+
replies?: Comment[]
|
|
144
|
+
is_hidden?: boolean
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
export interface Reaction {
|
|
148
|
+
id: string
|
|
149
|
+
user_id: string
|
|
150
|
+
target_id: string
|
|
151
|
+
target_type: 'post' | 'comment'
|
|
152
|
+
kind: string
|
|
153
|
+
created_at: string
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
export interface ThreadSummary {
|
|
157
|
+
id: string
|
|
158
|
+
space_id: string
|
|
159
|
+
slug: string
|
|
160
|
+
title: string
|
|
161
|
+
body?: string | null
|
|
162
|
+
reply_count: number
|
|
163
|
+
author_id: string
|
|
164
|
+
author?: {
|
|
165
|
+
id: string
|
|
166
|
+
name: string
|
|
167
|
+
handle?: string
|
|
168
|
+
avatar_url?: string | null
|
|
169
|
+
avatar?: unknown
|
|
170
|
+
} | null
|
|
171
|
+
created_at: string
|
|
172
|
+
tags?: Array<{
|
|
173
|
+
id: string
|
|
174
|
+
slug: string
|
|
175
|
+
label: string
|
|
176
|
+
}>
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
export interface AlbumSummary {
|
|
180
|
+
id: string
|
|
181
|
+
name: string
|
|
182
|
+
description?: string | null
|
|
183
|
+
media_count: number
|
|
184
|
+
owner: {
|
|
185
|
+
id: string
|
|
186
|
+
type: string
|
|
187
|
+
name?: string
|
|
188
|
+
avatar_url?: string | null
|
|
189
|
+
}
|
|
190
|
+
cover_media?: {
|
|
191
|
+
uuid: string
|
|
192
|
+
urls: {
|
|
193
|
+
thumb?: string
|
|
194
|
+
preview?: string
|
|
195
|
+
original?: string
|
|
196
|
+
}
|
|
197
|
+
} | null
|
|
198
|
+
created_at?: string | null
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
export interface FeedEntry {
|
|
202
|
+
id?: string
|
|
203
|
+
entity_id: string
|
|
204
|
+
entity_type: string
|
|
205
|
+
created_at?: string
|
|
206
|
+
activity_type?: string
|
|
207
|
+
actor_id?: string
|
|
208
|
+
owner_user_id?: string
|
|
209
|
+
visibility?: string
|
|
210
|
+
is_hidden?: boolean
|
|
211
|
+
post?: PostWithPendingState | null
|
|
212
|
+
thread?: ThreadSummary | null
|
|
213
|
+
album?: AlbumSummary | null
|
|
214
|
+
[key: string]: unknown
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
export interface ScheduledPostEntry {
|
|
218
|
+
id: string
|
|
219
|
+
status: string
|
|
220
|
+
publish_at: string
|
|
221
|
+
post_id: string | null
|
|
222
|
+
payload: Record<string, unknown> | string | null
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
export interface ScheduledPostsPage {
|
|
226
|
+
data: ScheduledPostEntry[]
|
|
227
|
+
meta: {
|
|
228
|
+
next_cursor: string | null
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
export type PendingPostStatus = 'pending' | 'uploading' | 'failed'
|
|
233
|
+
|
|
234
|
+
export interface PendingVideoRender {
|
|
235
|
+
sourceMediaUuid: string
|
|
236
|
+
renderJobId: string | null
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
export interface PendingPost {
|
|
240
|
+
tempId: string
|
|
241
|
+
body: string
|
|
242
|
+
share_type?: PostShareType | undefined
|
|
243
|
+
quoted_post_id?: string | undefined
|
|
244
|
+
visibility: string
|
|
245
|
+
content_warning?: string | undefined
|
|
246
|
+
meta?: PostMeta | undefined
|
|
247
|
+
media_ids?: string[] | undefined
|
|
248
|
+
mediaItems?: LocalMediaItem[] | undefined
|
|
249
|
+
hadUnuploadedMedia?: boolean | undefined
|
|
250
|
+
container_type?: string | undefined
|
|
251
|
+
container_id?: string | undefined
|
|
252
|
+
pendingVideoRenders?: PendingVideoRender[] | undefined
|
|
253
|
+
status: PendingPostStatus
|
|
254
|
+
createdAt: string
|
|
255
|
+
retryCount: number
|
|
256
|
+
error?: string | undefined
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
export interface RecoverablePendingDraft {
|
|
260
|
+
tempId: string
|
|
261
|
+
body: string
|
|
262
|
+
visibility: string
|
|
263
|
+
contentWarning?: string
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
export type ProcessPendingPostResult =
|
|
267
|
+
| {
|
|
268
|
+
ok: true
|
|
269
|
+
postId: string
|
|
270
|
+
isQuarantined?: boolean
|
|
271
|
+
}
|
|
272
|
+
| {
|
|
273
|
+
ok: false
|
|
274
|
+
error: string
|
|
275
|
+
retryable: boolean
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
export function isPost(obj: unknown): obj is Post {
|
|
279
|
+
return (
|
|
280
|
+
obj !== null
|
|
281
|
+
&& typeof obj === 'object'
|
|
282
|
+
&& 'id' in obj
|
|
283
|
+
&& 'body' in obj
|
|
284
|
+
&& 'author' in obj
|
|
285
|
+
&& 'reactions_count' in obj
|
|
286
|
+
&& 'comments_count' in obj
|
|
287
|
+
)
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
export function isComment(obj: unknown): obj is Comment {
|
|
291
|
+
return (
|
|
292
|
+
obj !== null
|
|
293
|
+
&& typeof obj === 'object'
|
|
294
|
+
&& 'id' in obj
|
|
295
|
+
&& 'body' in obj
|
|
296
|
+
&& 'post_id' in obj
|
|
297
|
+
&& 'author' in obj
|
|
298
|
+
)
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
export type PostUpdate = Partial<Omit<Post, 'id' | 'created_at' | 'author' | 'author_id'>>
|
|
302
|
+
export type CommentUpdate = Partial<Omit<Comment, 'id' | 'created_at' | 'author' | 'post_id'>>
|
|
303
|
+
|
|
304
|
+
export interface PostResponse {
|
|
305
|
+
data: Post
|
|
306
|
+
meta?: Record<string, unknown>
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
export interface PostListResponse {
|
|
310
|
+
data: Post[]
|
|
311
|
+
meta?: {
|
|
312
|
+
total: number
|
|
313
|
+
per_page: number
|
|
314
|
+
current_page: number
|
|
315
|
+
next_cursor?: string
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
export interface CommentListResponse {
|
|
320
|
+
data: Comment[]
|
|
321
|
+
meta?: {
|
|
322
|
+
total: number
|
|
323
|
+
next_cursor?: string
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
export enum PostVisibility {
|
|
328
|
+
PUBLIC = 'public',
|
|
329
|
+
PRIVATE = 'private',
|
|
330
|
+
FRIENDS = 'friends'
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
export enum ReactionKind {
|
|
334
|
+
LIKE = 'like',
|
|
335
|
+
LOVE = 'love',
|
|
336
|
+
HAHA = 'haha',
|
|
337
|
+
WOW = 'wow',
|
|
338
|
+
SAD = 'sad',
|
|
339
|
+
ANGRY = 'angry'
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
export interface ContentActiveRecipeMeta {
|
|
343
|
+
id: string
|
|
344
|
+
name: string
|
|
345
|
+
icon: string | null
|
|
346
|
+
is_preset: boolean
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
export interface ContentCurrentUser {
|
|
350
|
+
id: string
|
|
351
|
+
name: string
|
|
352
|
+
handle?: string | null
|
|
353
|
+
avatar?: string | null
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
export interface ContentStoreStorage {
|
|
357
|
+
getItem(key: string): string | null
|
|
358
|
+
setItem(key: string, value: string): void
|
|
359
|
+
removeItem(key: string): void
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
export interface ContentMediaUploadService {
|
|
363
|
+
uploadLocalMediaItems(items: LocalMediaItem[]): Promise<string[]>
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
export interface ContentStoreLogger {
|
|
367
|
+
error: (...args: unknown[]) => void
|
|
368
|
+
warn: (...args: unknown[]) => void
|
|
369
|
+
info: (...args: unknown[]) => void
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
export interface ContentStoreConfig {
|
|
373
|
+
client: ApiService
|
|
374
|
+
mediaUploadService: ContentMediaUploadService
|
|
375
|
+
getCurrentUser: () => ContentCurrentUser | null
|
|
376
|
+
syncActiveRecipe?: (meta: ContentActiveRecipeMeta | null) => void
|
|
377
|
+
storage?: ContentStoreStorage | null
|
|
378
|
+
pageSize?: number
|
|
379
|
+
logger?: ContentStoreLogger
|
|
380
|
+
storeId?: string
|
|
381
|
+
}
|
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Gamification-domain types shared across SocialKit frontends.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
export interface UserStats {
|
|
6
|
+
id: string
|
|
7
|
+
user_id: string
|
|
8
|
+
total_points: number
|
|
9
|
+
coin_balance: number
|
|
10
|
+
lifetime_points: number
|
|
11
|
+
current_level: number
|
|
12
|
+
level: ReputationLevel
|
|
13
|
+
next_level: ReputationLevel | null
|
|
14
|
+
level_progress: number
|
|
15
|
+
points_to_next_level: number
|
|
16
|
+
points_this_week: number
|
|
17
|
+
points_this_month: number
|
|
18
|
+
points_this_year?: number
|
|
19
|
+
rank?: number
|
|
20
|
+
percentile?: number
|
|
21
|
+
badges?: Badge[]
|
|
22
|
+
streaks?: {
|
|
23
|
+
current: number
|
|
24
|
+
longest: number
|
|
25
|
+
}
|
|
26
|
+
streak?: {
|
|
27
|
+
current_count: number
|
|
28
|
+
longest_streak: number
|
|
29
|
+
last_activity_at?: string
|
|
30
|
+
frozen: boolean
|
|
31
|
+
freeze_available: number
|
|
32
|
+
}
|
|
33
|
+
daily_limits?: {
|
|
34
|
+
points_awarded: number
|
|
35
|
+
max_points: number
|
|
36
|
+
points_remaining: number
|
|
37
|
+
is_reached: boolean
|
|
38
|
+
resets_at: string
|
|
39
|
+
}
|
|
40
|
+
privileges: UserPrivilege[]
|
|
41
|
+
stats: Record<string, unknown>
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export type UserReputation = UserStats
|
|
45
|
+
|
|
46
|
+
export interface ReputationLevel {
|
|
47
|
+
level_number: number
|
|
48
|
+
name: string
|
|
49
|
+
badge_color: string
|
|
50
|
+
badge_icon: string
|
|
51
|
+
benefits: string[]
|
|
52
|
+
min_points?: number
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export interface UserPrivilege {
|
|
56
|
+
id: string
|
|
57
|
+
slug: string
|
|
58
|
+
name: string
|
|
59
|
+
description: string
|
|
60
|
+
unlocked_at: string
|
|
61
|
+
expires_at?: string
|
|
62
|
+
category?: string
|
|
63
|
+
is_active?: boolean
|
|
64
|
+
privilege_id?: string
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export interface Achievement {
|
|
68
|
+
id: string
|
|
69
|
+
name: string
|
|
70
|
+
description: string
|
|
71
|
+
icon: string
|
|
72
|
+
rarity?: 'common' | 'uncommon' | 'rare' | 'epic' | 'legendary'
|
|
73
|
+
condition_type?: 'count' | 'streak' | 'points' | 'social'
|
|
74
|
+
condition_data?: {
|
|
75
|
+
action?: string
|
|
76
|
+
target: number
|
|
77
|
+
current?: number
|
|
78
|
+
}
|
|
79
|
+
reward_points?: number
|
|
80
|
+
points_awarded?: number
|
|
81
|
+
reward_data?: {
|
|
82
|
+
badge_color?: string
|
|
83
|
+
badge_text?: string
|
|
84
|
+
special_privileges?: string[]
|
|
85
|
+
unlocks_feature?: string
|
|
86
|
+
}
|
|
87
|
+
is_active?: boolean
|
|
88
|
+
is_visible?: boolean
|
|
89
|
+
is_unlocked?: boolean
|
|
90
|
+
is_claimed?: boolean
|
|
91
|
+
can_claim?: boolean
|
|
92
|
+
unlocked_at?: string | null
|
|
93
|
+
claimed_at?: string | null
|
|
94
|
+
progress_percentage?: number
|
|
95
|
+
progress_current?: number
|
|
96
|
+
progress_target?: number
|
|
97
|
+
share_card?: AchievementShareCard
|
|
98
|
+
progress?: number | AchievementProgress
|
|
99
|
+
sort_order?: number
|
|
100
|
+
requirements?: AchievementRequirement[]
|
|
101
|
+
category?: string
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export interface AchievementShareCard {
|
|
105
|
+
title: string
|
|
106
|
+
badge_label: string
|
|
107
|
+
description: string
|
|
108
|
+
image_url: string
|
|
109
|
+
share_url: string
|
|
110
|
+
share_text: string
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
export interface AchievementProgress {
|
|
114
|
+
current_value: number
|
|
115
|
+
target_value: number
|
|
116
|
+
percentage: number
|
|
117
|
+
unit: string
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export interface AchievementRequirement {
|
|
121
|
+
id: string
|
|
122
|
+
type: string
|
|
123
|
+
target_value: number
|
|
124
|
+
current_value: number
|
|
125
|
+
description: string
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
export interface AchievementUnlockNotification {
|
|
129
|
+
achievementId: string
|
|
130
|
+
title: string
|
|
131
|
+
description: string
|
|
132
|
+
icon: string
|
|
133
|
+
unlockedAt: string
|
|
134
|
+
points?: number
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
export interface Quest {
|
|
138
|
+
id: string
|
|
139
|
+
name?: string
|
|
140
|
+
title?: string
|
|
141
|
+
description: string
|
|
142
|
+
type: 'daily' | 'weekly' | 'monthly' | 'special' | 'challenge'
|
|
143
|
+
objectives: QuestObjective[]
|
|
144
|
+
rewards?: QuestReward[]
|
|
145
|
+
reward_points: number
|
|
146
|
+
status?: 'available' | 'in_progress' | 'completed' | 'expired'
|
|
147
|
+
is_active?: boolean
|
|
148
|
+
starts_at?: string
|
|
149
|
+
expires_at: string | null
|
|
150
|
+
completed_at: string | null
|
|
151
|
+
accepted_at?: string | null
|
|
152
|
+
progress?: {
|
|
153
|
+
current: number
|
|
154
|
+
total: number
|
|
155
|
+
percentage: number
|
|
156
|
+
}
|
|
157
|
+
progress_percentage?: number
|
|
158
|
+
category?: string
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
export interface QuestObjective {
|
|
162
|
+
id: string
|
|
163
|
+
quest_id?: string
|
|
164
|
+
description: string
|
|
165
|
+
type: string
|
|
166
|
+
target: number
|
|
167
|
+
target_value?: number
|
|
168
|
+
current: number
|
|
169
|
+
current_value?: number
|
|
170
|
+
is_completed?: boolean
|
|
171
|
+
completed?: boolean
|
|
172
|
+
bonus_points?: number
|
|
173
|
+
unit?: string
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
export interface QuestReward {
|
|
177
|
+
type: 'points' | 'badge' | 'privilege' | 'item'
|
|
178
|
+
value: number | string
|
|
179
|
+
description: string
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
export interface LeaderboardEntry {
|
|
183
|
+
rank: number
|
|
184
|
+
user_id: string
|
|
185
|
+
handle: string
|
|
186
|
+
name: string
|
|
187
|
+
avatar_url?: string | null
|
|
188
|
+
points: number
|
|
189
|
+
period_points?: number
|
|
190
|
+
total_points: number
|
|
191
|
+
level: number
|
|
192
|
+
current_level?: number
|
|
193
|
+
level_details?: ReputationLevel
|
|
194
|
+
achievements_count?: number
|
|
195
|
+
change: number
|
|
196
|
+
trend?: number | 'up' | 'down' | 'same' | null
|
|
197
|
+
is_current_user: boolean
|
|
198
|
+
space_id?: string | null
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
export type LeaderboardPeriod = 'daily' | 'weekly' | 'monthly' | 'all-time'
|
|
202
|
+
export type QuestFilter = 'active' | 'daily' | 'weekly' | 'completed'
|
|
203
|
+
|
|
204
|
+
export interface Reward {
|
|
205
|
+
id: string
|
|
206
|
+
name: string
|
|
207
|
+
description: string
|
|
208
|
+
cost_points: number
|
|
209
|
+
reward_type?: 'badge' | 'title' | 'cosmetic' | 'boost' | 'feature'
|
|
210
|
+
type?: 'cosmetic' | 'privilege' | 'boost' | 'item'
|
|
211
|
+
category?: 'badge' | 'privilege' | 'cosmetic' | 'bonus'
|
|
212
|
+
icon?: string
|
|
213
|
+
preview_image?: string
|
|
214
|
+
reward_data?: Record<string, unknown>
|
|
215
|
+
can_redeem?: boolean
|
|
216
|
+
user_points?: number
|
|
217
|
+
points_needed?: number
|
|
218
|
+
stock_quantity?: number | null
|
|
219
|
+
stock_remaining?: number | null
|
|
220
|
+
max_per_user?: number
|
|
221
|
+
user_redemptions?: number
|
|
222
|
+
availability_status?: 'available' | 'insufficient_points' | 'out_of_stock' | 'limit_reached' | 'inactive' | string
|
|
223
|
+
data?: {
|
|
224
|
+
duration?: number
|
|
225
|
+
value?: unknown
|
|
226
|
+
icon?: string
|
|
227
|
+
color?: string
|
|
228
|
+
}
|
|
229
|
+
stock?: number
|
|
230
|
+
limited_quantity?: number | null
|
|
231
|
+
remaining_quantity?: number | null
|
|
232
|
+
redemption_limit?: number
|
|
233
|
+
is_available?: boolean
|
|
234
|
+
is_claimed?: boolean
|
|
235
|
+
redeemed_count?: number
|
|
236
|
+
redeemed_at?: string
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
export interface ClaimedReward {
|
|
240
|
+
id: string
|
|
241
|
+
reward_id: string
|
|
242
|
+
reward: Reward
|
|
243
|
+
claimed_at: string
|
|
244
|
+
status: 'active' | 'expired'
|
|
245
|
+
expires_at?: string
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
export interface RewardTransaction {
|
|
249
|
+
id: string
|
|
250
|
+
reward_id: string
|
|
251
|
+
reward: Reward
|
|
252
|
+
points_spent: number
|
|
253
|
+
transaction_type: 'redemption' | 'refund'
|
|
254
|
+
created_at: string
|
|
255
|
+
metadata: Record<string, unknown>
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
export interface Badge {
|
|
259
|
+
id: string
|
|
260
|
+
name: string
|
|
261
|
+
description: string
|
|
262
|
+
icon: string
|
|
263
|
+
color: string
|
|
264
|
+
rarity: 'common' | 'uncommon' | 'rare' | 'epic' | 'legendary'
|
|
265
|
+
earned_at: string
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
export interface GamificationNotification {
|
|
269
|
+
type: 'points_earned' | 'level_up' | 'achievement_unlocked' | 'quest_completed' | 'leaderboard_change' | 'reward_available'
|
|
270
|
+
data: unknown
|
|
271
|
+
timestamp: string
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
export interface PointTransaction {
|
|
275
|
+
id: string
|
|
276
|
+
user_id: string
|
|
277
|
+
points: number
|
|
278
|
+
type: string
|
|
279
|
+
source_type?: string
|
|
280
|
+
source_id?: string
|
|
281
|
+
description: string
|
|
282
|
+
created_at: string
|
|
283
|
+
is_reversed?: boolean
|
|
284
|
+
reversed_at?: string
|
|
285
|
+
reversal_reason?: string
|
|
286
|
+
}
|