@serhii.olishevskyi/docs 1.1.8 → 1.2.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/{UserPopoverComponent-5F4S3X4F.mjs → UserPopoverComponent-FZF757NQ.mjs} +1 -1
- package/dist/{chunk-UA57YNRJ.mjs → chunk-FYNGJLO7.mjs} +2 -0
- package/dist/index.d.mts +79 -1
- package/dist/index.d.ts +79 -1
- package/dist/index.js +98 -1
- package/dist/index.mjs +96 -3
- package/package.json +1 -1
|
@@ -2546,6 +2546,7 @@ var UserPopoverComponent = ({
|
|
|
2546
2546
|
var UserPopoverComponent_default = UserPopoverComponent;
|
|
2547
2547
|
|
|
2548
2548
|
export {
|
|
2549
|
+
getDeviceId,
|
|
2549
2550
|
fetchCompanySessions,
|
|
2550
2551
|
trackUserSession,
|
|
2551
2552
|
trackUserSessionByRoute,
|
|
@@ -2580,6 +2581,7 @@ export {
|
|
|
2580
2581
|
useConfirmation,
|
|
2581
2582
|
AppSettingsProvider,
|
|
2582
2583
|
useAppSettings,
|
|
2584
|
+
defaultUserSettings,
|
|
2583
2585
|
UserSettingsProvider,
|
|
2584
2586
|
useUserSettings,
|
|
2585
2587
|
Providers,
|
package/dist/index.d.mts
CHANGED
|
@@ -182,6 +182,7 @@ interface UserSettings {
|
|
|
182
182
|
created_at?: string;
|
|
183
183
|
updated_at?: string;
|
|
184
184
|
}
|
|
185
|
+
declare const defaultUserSettings: Omit<UserSettings, 'id'>;
|
|
185
186
|
|
|
186
187
|
type MembershipRole = 'superadmin' | 'admin' | 'user';
|
|
187
188
|
interface Membership {
|
|
@@ -199,6 +200,76 @@ interface Membership {
|
|
|
199
200
|
locked_reason: string | null;
|
|
200
201
|
excluded: boolean;
|
|
201
202
|
}
|
|
203
|
+
interface CompanyMember {
|
|
204
|
+
id: string;
|
|
205
|
+
userId: string;
|
|
206
|
+
companyId: string;
|
|
207
|
+
role: string;
|
|
208
|
+
employeePost: string | null;
|
|
209
|
+
displayName: string;
|
|
210
|
+
email: string;
|
|
211
|
+
avatarUrl: string | null;
|
|
212
|
+
}
|
|
213
|
+
interface SaveCompanyUserPayload {
|
|
214
|
+
company_id: string;
|
|
215
|
+
membership_id?: string;
|
|
216
|
+
user_id?: string;
|
|
217
|
+
email: string;
|
|
218
|
+
first_name?: string | null;
|
|
219
|
+
middle_name?: string | null;
|
|
220
|
+
last_name?: string | null;
|
|
221
|
+
display_name?: string | null;
|
|
222
|
+
phone?: string | null;
|
|
223
|
+
birthday?: string | null;
|
|
224
|
+
description?: string | null;
|
|
225
|
+
name_order?: 'first_last' | 'last_first';
|
|
226
|
+
include_middle_name?: boolean;
|
|
227
|
+
name_genitive?: string;
|
|
228
|
+
name_dative?: string;
|
|
229
|
+
name_instrumental?: string;
|
|
230
|
+
name_vocative?: string;
|
|
231
|
+
role: MembershipRole;
|
|
232
|
+
employee_post?: string | null;
|
|
233
|
+
work_schedule_id?: string | null;
|
|
234
|
+
locked?: boolean;
|
|
235
|
+
locked_reason?: string | null;
|
|
236
|
+
excluded?: boolean;
|
|
237
|
+
langCode?: string;
|
|
238
|
+
requestUser?: string;
|
|
239
|
+
}
|
|
240
|
+
interface FullCompanyMemberItem {
|
|
241
|
+
id: string;
|
|
242
|
+
membership_id: string;
|
|
243
|
+
company_id: string;
|
|
244
|
+
user_id: string;
|
|
245
|
+
role: MembershipRole;
|
|
246
|
+
employee_post: string | null;
|
|
247
|
+
work_schedule_id: string | null;
|
|
248
|
+
locked: boolean;
|
|
249
|
+
locked_reason: string | null;
|
|
250
|
+
excluded: boolean;
|
|
251
|
+
first_login_at?: string | null;
|
|
252
|
+
last_login_at?: string | null;
|
|
253
|
+
email: string;
|
|
254
|
+
first_name: string | null;
|
|
255
|
+
middle_name: string | null;
|
|
256
|
+
last_name: string | null;
|
|
257
|
+
display_name: string | null;
|
|
258
|
+
phone: string | null;
|
|
259
|
+
birthday: string | null;
|
|
260
|
+
avatar_url: string | null;
|
|
261
|
+
avatar_path: string | null;
|
|
262
|
+
description: string | null;
|
|
263
|
+
name_order?: 'first_last' | 'last_first';
|
|
264
|
+
include_middle_name?: boolean;
|
|
265
|
+
name_genitive?: string;
|
|
266
|
+
name_dative?: string;
|
|
267
|
+
name_instrumental?: string;
|
|
268
|
+
name_vocative?: string;
|
|
269
|
+
profile_archived?: boolean;
|
|
270
|
+
profile_locked?: boolean;
|
|
271
|
+
created_at: string;
|
|
272
|
+
}
|
|
202
273
|
|
|
203
274
|
interface UserRoleChipComponentProps {
|
|
204
275
|
overrideNamespace?: string;
|
|
@@ -571,10 +642,17 @@ declare const Services: {
|
|
|
571
642
|
};
|
|
572
643
|
};
|
|
573
644
|
|
|
645
|
+
type UserStatusType = 'online' | 'away' | 'offline';
|
|
646
|
+
|
|
574
647
|
declare function useDebounce<T>(value: T, delay?: number): T;
|
|
575
648
|
|
|
576
649
|
declare const Hooks: {
|
|
577
650
|
readonly useDebounce: typeof useDebounce;
|
|
651
|
+
readonly useUserStatus: (userId?: string, initialLastSeenAt?: string | null, currentAuthUserId?: string) => {
|
|
652
|
+
status: UserStatusType;
|
|
653
|
+
isOnline: boolean;
|
|
654
|
+
lastSeen: string | null;
|
|
655
|
+
};
|
|
578
656
|
};
|
|
579
657
|
|
|
580
|
-
export { type AIConfig, type AIGenerateOptions, AIProvider, type AIProviderProps, type AIProviderType, AppSettingsProvider, AuthProvider, BreadcrumbProvider, type ConfirmOptions, type ConfirmResult, ConfirmationProvider, type ConfirmationProviderProps, type CopyClipboardButtonComponentProps, type DialogSeverity, type DisplayState, type EmailInputComponentProps, type ExpandableNoteComponentProps, Hooks, type Language, LocalizationProvider, type MyAvatarComponentProps, type NumberInputComponentProps, Providers, type SearchComponentProps, type SelectComponentProps, type SelectOption, Services, type SupabaseConfig, SupabaseProvider, type SupabaseProviderProps, type TextFieldComponentProps, type ThemeColors, type ThemeConfig, type ThemeMode, ThemeProvider, ToastProvider, type ToastType, type TranslatableTooltipComponentProps, TranslateProvider, TranslateText, TranslationEditProvider, type TypographyConfig, UI, type UrlComponentProps as UrlProps, type UserAvatarComponentProps, type UserGroupedSessions, type UserPopoverComponentProps, type UserRoleChipComponentProps, type UserSessionItem, UserSettingsProvider, type UserStatusChipComponentProps, useAI, useAppSettings, useAppTheme, useAuth, useBreadcrumb, useConfirmation, useLocalization, useSupabase, useToast, useTranslationEdit, useTranslationNamespace, useUserSettings };
|
|
658
|
+
export { type AIConfig, type AIGenerateOptions, AIProvider, type AIProviderProps, type AIProviderType, AppSettingsProvider, AuthProvider, BreadcrumbProvider, type CompanyMember, type ConfirmOptions, type ConfirmResult, ConfirmationProvider, type ConfirmationProviderProps, type CopyClipboardButtonComponentProps, type DialogSeverity, type DisplayState, type EmailInputComponentProps, type ExpandableNoteComponentProps, type FullCompanyMemberItem, Hooks, type Language, LocalizationProvider, type Membership, type MembershipRole, type MyAvatarComponentProps, type NumberInputComponentProps, Providers, type SaveCompanyUserPayload, type SearchComponentProps, type SelectComponentProps, type SelectOption, Services, type SupabaseConfig, SupabaseProvider, type SupabaseProviderProps, type TextFieldComponentProps, type ThemeColors, type ThemeConfig, type ThemeMode, ThemeProvider, ToastProvider, type ToastType, type TranslatableTooltipComponentProps, TranslateProvider, TranslateText, TranslationEditProvider, type TypographyConfig, UI, type UrlComponentProps as UrlProps, type UserAvatarComponentProps, type UserGroupedSessions, type UserPopoverComponentProps, type UserProfile, type UserRoleChipComponentProps, type UserSessionItem, type UserSettings, UserSettingsProvider, type UserStatusChipComponentProps, defaultUserSettings, useAI, useAppSettings, useAppTheme, useAuth, useBreadcrumb, useConfirmation, useLocalization, useSupabase, useToast, useTranslationEdit, useTranslationNamespace, useUserSettings };
|
package/dist/index.d.ts
CHANGED
|
@@ -182,6 +182,7 @@ interface UserSettings {
|
|
|
182
182
|
created_at?: string;
|
|
183
183
|
updated_at?: string;
|
|
184
184
|
}
|
|
185
|
+
declare const defaultUserSettings: Omit<UserSettings, 'id'>;
|
|
185
186
|
|
|
186
187
|
type MembershipRole = 'superadmin' | 'admin' | 'user';
|
|
187
188
|
interface Membership {
|
|
@@ -199,6 +200,76 @@ interface Membership {
|
|
|
199
200
|
locked_reason: string | null;
|
|
200
201
|
excluded: boolean;
|
|
201
202
|
}
|
|
203
|
+
interface CompanyMember {
|
|
204
|
+
id: string;
|
|
205
|
+
userId: string;
|
|
206
|
+
companyId: string;
|
|
207
|
+
role: string;
|
|
208
|
+
employeePost: string | null;
|
|
209
|
+
displayName: string;
|
|
210
|
+
email: string;
|
|
211
|
+
avatarUrl: string | null;
|
|
212
|
+
}
|
|
213
|
+
interface SaveCompanyUserPayload {
|
|
214
|
+
company_id: string;
|
|
215
|
+
membership_id?: string;
|
|
216
|
+
user_id?: string;
|
|
217
|
+
email: string;
|
|
218
|
+
first_name?: string | null;
|
|
219
|
+
middle_name?: string | null;
|
|
220
|
+
last_name?: string | null;
|
|
221
|
+
display_name?: string | null;
|
|
222
|
+
phone?: string | null;
|
|
223
|
+
birthday?: string | null;
|
|
224
|
+
description?: string | null;
|
|
225
|
+
name_order?: 'first_last' | 'last_first';
|
|
226
|
+
include_middle_name?: boolean;
|
|
227
|
+
name_genitive?: string;
|
|
228
|
+
name_dative?: string;
|
|
229
|
+
name_instrumental?: string;
|
|
230
|
+
name_vocative?: string;
|
|
231
|
+
role: MembershipRole;
|
|
232
|
+
employee_post?: string | null;
|
|
233
|
+
work_schedule_id?: string | null;
|
|
234
|
+
locked?: boolean;
|
|
235
|
+
locked_reason?: string | null;
|
|
236
|
+
excluded?: boolean;
|
|
237
|
+
langCode?: string;
|
|
238
|
+
requestUser?: string;
|
|
239
|
+
}
|
|
240
|
+
interface FullCompanyMemberItem {
|
|
241
|
+
id: string;
|
|
242
|
+
membership_id: string;
|
|
243
|
+
company_id: string;
|
|
244
|
+
user_id: string;
|
|
245
|
+
role: MembershipRole;
|
|
246
|
+
employee_post: string | null;
|
|
247
|
+
work_schedule_id: string | null;
|
|
248
|
+
locked: boolean;
|
|
249
|
+
locked_reason: string | null;
|
|
250
|
+
excluded: boolean;
|
|
251
|
+
first_login_at?: string | null;
|
|
252
|
+
last_login_at?: string | null;
|
|
253
|
+
email: string;
|
|
254
|
+
first_name: string | null;
|
|
255
|
+
middle_name: string | null;
|
|
256
|
+
last_name: string | null;
|
|
257
|
+
display_name: string | null;
|
|
258
|
+
phone: string | null;
|
|
259
|
+
birthday: string | null;
|
|
260
|
+
avatar_url: string | null;
|
|
261
|
+
avatar_path: string | null;
|
|
262
|
+
description: string | null;
|
|
263
|
+
name_order?: 'first_last' | 'last_first';
|
|
264
|
+
include_middle_name?: boolean;
|
|
265
|
+
name_genitive?: string;
|
|
266
|
+
name_dative?: string;
|
|
267
|
+
name_instrumental?: string;
|
|
268
|
+
name_vocative?: string;
|
|
269
|
+
profile_archived?: boolean;
|
|
270
|
+
profile_locked?: boolean;
|
|
271
|
+
created_at: string;
|
|
272
|
+
}
|
|
202
273
|
|
|
203
274
|
interface UserRoleChipComponentProps {
|
|
204
275
|
overrideNamespace?: string;
|
|
@@ -571,10 +642,17 @@ declare const Services: {
|
|
|
571
642
|
};
|
|
572
643
|
};
|
|
573
644
|
|
|
645
|
+
type UserStatusType = 'online' | 'away' | 'offline';
|
|
646
|
+
|
|
574
647
|
declare function useDebounce<T>(value: T, delay?: number): T;
|
|
575
648
|
|
|
576
649
|
declare const Hooks: {
|
|
577
650
|
readonly useDebounce: typeof useDebounce;
|
|
651
|
+
readonly useUserStatus: (userId?: string, initialLastSeenAt?: string | null, currentAuthUserId?: string) => {
|
|
652
|
+
status: UserStatusType;
|
|
653
|
+
isOnline: boolean;
|
|
654
|
+
lastSeen: string | null;
|
|
655
|
+
};
|
|
578
656
|
};
|
|
579
657
|
|
|
580
|
-
export { type AIConfig, type AIGenerateOptions, AIProvider, type AIProviderProps, type AIProviderType, AppSettingsProvider, AuthProvider, BreadcrumbProvider, type ConfirmOptions, type ConfirmResult, ConfirmationProvider, type ConfirmationProviderProps, type CopyClipboardButtonComponentProps, type DialogSeverity, type DisplayState, type EmailInputComponentProps, type ExpandableNoteComponentProps, Hooks, type Language, LocalizationProvider, type MyAvatarComponentProps, type NumberInputComponentProps, Providers, type SearchComponentProps, type SelectComponentProps, type SelectOption, Services, type SupabaseConfig, SupabaseProvider, type SupabaseProviderProps, type TextFieldComponentProps, type ThemeColors, type ThemeConfig, type ThemeMode, ThemeProvider, ToastProvider, type ToastType, type TranslatableTooltipComponentProps, TranslateProvider, TranslateText, TranslationEditProvider, type TypographyConfig, UI, type UrlComponentProps as UrlProps, type UserAvatarComponentProps, type UserGroupedSessions, type UserPopoverComponentProps, type UserRoleChipComponentProps, type UserSessionItem, UserSettingsProvider, type UserStatusChipComponentProps, useAI, useAppSettings, useAppTheme, useAuth, useBreadcrumb, useConfirmation, useLocalization, useSupabase, useToast, useTranslationEdit, useTranslationNamespace, useUserSettings };
|
|
658
|
+
export { type AIConfig, type AIGenerateOptions, AIProvider, type AIProviderProps, type AIProviderType, AppSettingsProvider, AuthProvider, BreadcrumbProvider, type CompanyMember, type ConfirmOptions, type ConfirmResult, ConfirmationProvider, type ConfirmationProviderProps, type CopyClipboardButtonComponentProps, type DialogSeverity, type DisplayState, type EmailInputComponentProps, type ExpandableNoteComponentProps, type FullCompanyMemberItem, Hooks, type Language, LocalizationProvider, type Membership, type MembershipRole, type MyAvatarComponentProps, type NumberInputComponentProps, Providers, type SaveCompanyUserPayload, type SearchComponentProps, type SelectComponentProps, type SelectOption, Services, type SupabaseConfig, SupabaseProvider, type SupabaseProviderProps, type TextFieldComponentProps, type ThemeColors, type ThemeConfig, type ThemeMode, ThemeProvider, ToastProvider, type ToastType, type TranslatableTooltipComponentProps, TranslateProvider, TranslateText, TranslationEditProvider, type TypographyConfig, UI, type UrlComponentProps as UrlProps, type UserAvatarComponentProps, type UserGroupedSessions, type UserPopoverComponentProps, type UserProfile, type UserRoleChipComponentProps, type UserSessionItem, type UserSettings, UserSettingsProvider, type UserStatusChipComponentProps, defaultUserSettings, useAI, useAppSettings, useAppTheme, useAuth, useBreadcrumb, useConfirmation, useLocalization, useSupabase, useToast, useTranslationEdit, useTranslationNamespace, useUserSettings };
|
package/dist/index.js
CHANGED
|
@@ -2760,6 +2760,7 @@ __export(index_exports, {
|
|
|
2760
2760
|
TranslationEditProvider: () => TranslationEditProvider,
|
|
2761
2761
|
UI: () => UI,
|
|
2762
2762
|
UserSettingsProvider: () => UserSettingsProvider,
|
|
2763
|
+
defaultUserSettings: () => defaultUserSettings,
|
|
2763
2764
|
useAI: () => useAI,
|
|
2764
2765
|
useAppSettings: () => useAppSettings,
|
|
2765
2766
|
useAppTheme: () => useAppTheme,
|
|
@@ -4408,6 +4409,9 @@ var UI = {
|
|
|
4408
4409
|
}
|
|
4409
4410
|
};
|
|
4410
4411
|
|
|
4412
|
+
// src/types/index.ts
|
|
4413
|
+
init_user_types();
|
|
4414
|
+
|
|
4411
4415
|
// src/index.ts
|
|
4412
4416
|
init_context();
|
|
4413
4417
|
init_context();
|
|
@@ -4427,9 +4431,101 @@ var Services = {
|
|
|
4427
4431
|
}
|
|
4428
4432
|
};
|
|
4429
4433
|
|
|
4434
|
+
// src/hooks/useUserStatus.ts
|
|
4435
|
+
var import_react28 = require("react");
|
|
4436
|
+
init_deviceId();
|
|
4437
|
+
init_context();
|
|
4438
|
+
var ONLINE_THRESHOLD_MINUTES = 2;
|
|
4439
|
+
var AWAY_THRESHOLD_MINUTES = 15;
|
|
4440
|
+
var useUserStatus2 = (userId, initialLastSeenAt, currentAuthUserId) => {
|
|
4441
|
+
const supabase = useSupabase();
|
|
4442
|
+
const [status, setStatus] = (0, import_react28.useState)("offline");
|
|
4443
|
+
const [lastSeen, setLastSeen] = (0, import_react28.useState)(initialLastSeenAt ?? null);
|
|
4444
|
+
const lastSeenRef = (0, import_react28.useRef)(initialLastSeenAt ?? null);
|
|
4445
|
+
lastSeenRef.current = lastSeen;
|
|
4446
|
+
const calculateStatus = (isOnline, lastSeenIso) => {
|
|
4447
|
+
if (isOnline) return "online";
|
|
4448
|
+
if (!lastSeenIso) return "offline";
|
|
4449
|
+
const lastSeenTime = new Date(lastSeenIso).getTime();
|
|
4450
|
+
if (isNaN(lastSeenTime)) return "offline";
|
|
4451
|
+
const diffInMinutes = (Date.now() - lastSeenTime) / (1e3 * 60);
|
|
4452
|
+
if (diffInMinutes >= 0 && diffInMinutes <= ONLINE_THRESHOLD_MINUTES) {
|
|
4453
|
+
return "online";
|
|
4454
|
+
}
|
|
4455
|
+
if (diffInMinutes > ONLINE_THRESHOLD_MINUTES && diffInMinutes <= AWAY_THRESHOLD_MINUTES) {
|
|
4456
|
+
return "away";
|
|
4457
|
+
}
|
|
4458
|
+
return "offline";
|
|
4459
|
+
};
|
|
4460
|
+
(0, import_react28.useEffect)(() => {
|
|
4461
|
+
if (!userId) return;
|
|
4462
|
+
let isMounted = true;
|
|
4463
|
+
const isSelf = currentAuthUserId && userId === currentAuthUserId;
|
|
4464
|
+
const fetchLastSeen = async () => {
|
|
4465
|
+
if (initialLastSeenAt !== void 0) return;
|
|
4466
|
+
let query = supabase.from("user_sessions").select("last_seen_at").eq("user_id", userId);
|
|
4467
|
+
if (isSelf) {
|
|
4468
|
+
query = query.eq("device_id", getDeviceId());
|
|
4469
|
+
} else {
|
|
4470
|
+
query = query.order("last_seen_at", { ascending: false });
|
|
4471
|
+
}
|
|
4472
|
+
const { data, error } = await query.limit(1).maybeSingle();
|
|
4473
|
+
if (error) {
|
|
4474
|
+
console.warn(`[useUserStatus] Error fetching session for ${userId}:`, error.message);
|
|
4475
|
+
return;
|
|
4476
|
+
}
|
|
4477
|
+
if (data && isMounted) {
|
|
4478
|
+
setLastSeen(data.last_seen_at);
|
|
4479
|
+
setStatus(calculateStatus(false, data.last_seen_at));
|
|
4480
|
+
}
|
|
4481
|
+
};
|
|
4482
|
+
fetchLastSeen();
|
|
4483
|
+
const channel = supabase.channel(`presence_user_${userId}`);
|
|
4484
|
+
channel.on("presence", { event: "sync" }, () => {
|
|
4485
|
+
const state = channel.presenceState();
|
|
4486
|
+
const isOnline = Object.keys(state).length > 0;
|
|
4487
|
+
if (isMounted) {
|
|
4488
|
+
setStatus(isOnline ? "online" : calculateStatus(false, lastSeenRef.current));
|
|
4489
|
+
}
|
|
4490
|
+
}).on("presence", { event: "join" }, () => {
|
|
4491
|
+
if (isMounted) setStatus("online");
|
|
4492
|
+
}).on("presence", { event: "leave" }, () => {
|
|
4493
|
+
const nowIso = (/* @__PURE__ */ new Date()).toISOString();
|
|
4494
|
+
if (isMounted) {
|
|
4495
|
+
setLastSeen(nowIso);
|
|
4496
|
+
setStatus(calculateStatus(false, nowIso));
|
|
4497
|
+
}
|
|
4498
|
+
}).on(
|
|
4499
|
+
"postgres_changes",
|
|
4500
|
+
{
|
|
4501
|
+
event: "*",
|
|
4502
|
+
schema: "public",
|
|
4503
|
+
table: "user_sessions",
|
|
4504
|
+
filter: isSelf ? `device_id=eq.${getDeviceId()}` : `user_id=eq.${userId}`
|
|
4505
|
+
},
|
|
4506
|
+
(payload) => {
|
|
4507
|
+
if (!isMounted) return;
|
|
4508
|
+
const newLastSeen = payload.new?.last_seen_at ?? (/* @__PURE__ */ new Date()).toISOString();
|
|
4509
|
+
setLastSeen(newLastSeen);
|
|
4510
|
+
setStatus(calculateStatus(false, newLastSeen));
|
|
4511
|
+
}
|
|
4512
|
+
).subscribe();
|
|
4513
|
+
return () => {
|
|
4514
|
+
isMounted = false;
|
|
4515
|
+
supabase.removeChannel(channel);
|
|
4516
|
+
};
|
|
4517
|
+
}, [userId, initialLastSeenAt, currentAuthUserId]);
|
|
4518
|
+
return {
|
|
4519
|
+
status,
|
|
4520
|
+
isOnline: status === "online",
|
|
4521
|
+
lastSeen
|
|
4522
|
+
};
|
|
4523
|
+
};
|
|
4524
|
+
|
|
4430
4525
|
// src/hooks/index.ts
|
|
4431
4526
|
var Hooks = {
|
|
4432
|
-
useDebounce
|
|
4527
|
+
useDebounce,
|
|
4528
|
+
useUserStatus: useUserStatus2
|
|
4433
4529
|
};
|
|
4434
4530
|
// Annotate the CommonJS export names for ESM import in node:
|
|
4435
4531
|
0 && (module.exports = {
|
|
@@ -4450,6 +4546,7 @@ var Hooks = {
|
|
|
4450
4546
|
TranslationEditProvider,
|
|
4451
4547
|
UI,
|
|
4452
4548
|
UserSettingsProvider,
|
|
4549
|
+
defaultUserSettings,
|
|
4453
4550
|
useAI,
|
|
4454
4551
|
useAppSettings,
|
|
4455
4552
|
useAppTheme,
|
package/dist/index.mjs
CHANGED
|
@@ -19,8 +19,10 @@ import {
|
|
|
19
19
|
UserRoleChipComponent,
|
|
20
20
|
UserSettingsProvider,
|
|
21
21
|
UserStatusChipComponent,
|
|
22
|
+
defaultUserSettings,
|
|
22
23
|
fetchCompanySessions,
|
|
23
24
|
fetchUserSessions,
|
|
25
|
+
getDeviceId,
|
|
24
26
|
getUserLastSeenAt,
|
|
25
27
|
getUsersLastSeenMap,
|
|
26
28
|
groupSessionsByUser,
|
|
@@ -40,7 +42,7 @@ import {
|
|
|
40
42
|
useTranslationEdit,
|
|
41
43
|
useTranslationNamespace,
|
|
42
44
|
useUserSettings
|
|
43
|
-
} from "./chunk-
|
|
45
|
+
} from "./chunk-FYNGJLO7.mjs";
|
|
44
46
|
|
|
45
47
|
// src/UI/components/inputs/TextFieldComponent.tsx
|
|
46
48
|
import { useState } from "react";
|
|
@@ -738,7 +740,7 @@ var EmailInputComponent = ({
|
|
|
738
740
|
import { useState as useState5, useEffect as useEffect2, lazy, Suspense } from "react";
|
|
739
741
|
import { Avatar, Tooltip as Tooltip3, Typography as Typography2 } from "@mui/material";
|
|
740
742
|
import { Fragment as Fragment4, jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
741
|
-
var LazyUserPopover = lazy(() => import("./UserPopoverComponent-
|
|
743
|
+
var LazyUserPopover = lazy(() => import("./UserPopoverComponent-FZF757NQ.mjs"));
|
|
742
744
|
var getInitials = (name) => {
|
|
743
745
|
if (!name) return "?";
|
|
744
746
|
const parts = name.trim().split(" ");
|
|
@@ -1695,9 +1697,99 @@ var Services = {
|
|
|
1695
1697
|
}
|
|
1696
1698
|
};
|
|
1697
1699
|
|
|
1700
|
+
// src/hooks/useUserStatus.ts
|
|
1701
|
+
import { useEffect as useEffect6, useRef, useState as useState11 } from "react";
|
|
1702
|
+
var ONLINE_THRESHOLD_MINUTES = 2;
|
|
1703
|
+
var AWAY_THRESHOLD_MINUTES = 15;
|
|
1704
|
+
var useUserStatus = (userId, initialLastSeenAt, currentAuthUserId) => {
|
|
1705
|
+
const supabase = useSupabase();
|
|
1706
|
+
const [status, setStatus] = useState11("offline");
|
|
1707
|
+
const [lastSeen, setLastSeen] = useState11(initialLastSeenAt ?? null);
|
|
1708
|
+
const lastSeenRef = useRef(initialLastSeenAt ?? null);
|
|
1709
|
+
lastSeenRef.current = lastSeen;
|
|
1710
|
+
const calculateStatus = (isOnline, lastSeenIso) => {
|
|
1711
|
+
if (isOnline) return "online";
|
|
1712
|
+
if (!lastSeenIso) return "offline";
|
|
1713
|
+
const lastSeenTime = new Date(lastSeenIso).getTime();
|
|
1714
|
+
if (isNaN(lastSeenTime)) return "offline";
|
|
1715
|
+
const diffInMinutes = (Date.now() - lastSeenTime) / (1e3 * 60);
|
|
1716
|
+
if (diffInMinutes >= 0 && diffInMinutes <= ONLINE_THRESHOLD_MINUTES) {
|
|
1717
|
+
return "online";
|
|
1718
|
+
}
|
|
1719
|
+
if (diffInMinutes > ONLINE_THRESHOLD_MINUTES && diffInMinutes <= AWAY_THRESHOLD_MINUTES) {
|
|
1720
|
+
return "away";
|
|
1721
|
+
}
|
|
1722
|
+
return "offline";
|
|
1723
|
+
};
|
|
1724
|
+
useEffect6(() => {
|
|
1725
|
+
if (!userId) return;
|
|
1726
|
+
let isMounted = true;
|
|
1727
|
+
const isSelf = currentAuthUserId && userId === currentAuthUserId;
|
|
1728
|
+
const fetchLastSeen = async () => {
|
|
1729
|
+
if (initialLastSeenAt !== void 0) return;
|
|
1730
|
+
let query = supabase.from("user_sessions").select("last_seen_at").eq("user_id", userId);
|
|
1731
|
+
if (isSelf) {
|
|
1732
|
+
query = query.eq("device_id", getDeviceId());
|
|
1733
|
+
} else {
|
|
1734
|
+
query = query.order("last_seen_at", { ascending: false });
|
|
1735
|
+
}
|
|
1736
|
+
const { data, error } = await query.limit(1).maybeSingle();
|
|
1737
|
+
if (error) {
|
|
1738
|
+
console.warn(`[useUserStatus] Error fetching session for ${userId}:`, error.message);
|
|
1739
|
+
return;
|
|
1740
|
+
}
|
|
1741
|
+
if (data && isMounted) {
|
|
1742
|
+
setLastSeen(data.last_seen_at);
|
|
1743
|
+
setStatus(calculateStatus(false, data.last_seen_at));
|
|
1744
|
+
}
|
|
1745
|
+
};
|
|
1746
|
+
fetchLastSeen();
|
|
1747
|
+
const channel = supabase.channel(`presence_user_${userId}`);
|
|
1748
|
+
channel.on("presence", { event: "sync" }, () => {
|
|
1749
|
+
const state = channel.presenceState();
|
|
1750
|
+
const isOnline = Object.keys(state).length > 0;
|
|
1751
|
+
if (isMounted) {
|
|
1752
|
+
setStatus(isOnline ? "online" : calculateStatus(false, lastSeenRef.current));
|
|
1753
|
+
}
|
|
1754
|
+
}).on("presence", { event: "join" }, () => {
|
|
1755
|
+
if (isMounted) setStatus("online");
|
|
1756
|
+
}).on("presence", { event: "leave" }, () => {
|
|
1757
|
+
const nowIso = (/* @__PURE__ */ new Date()).toISOString();
|
|
1758
|
+
if (isMounted) {
|
|
1759
|
+
setLastSeen(nowIso);
|
|
1760
|
+
setStatus(calculateStatus(false, nowIso));
|
|
1761
|
+
}
|
|
1762
|
+
}).on(
|
|
1763
|
+
"postgres_changes",
|
|
1764
|
+
{
|
|
1765
|
+
event: "*",
|
|
1766
|
+
schema: "public",
|
|
1767
|
+
table: "user_sessions",
|
|
1768
|
+
filter: isSelf ? `device_id=eq.${getDeviceId()}` : `user_id=eq.${userId}`
|
|
1769
|
+
},
|
|
1770
|
+
(payload) => {
|
|
1771
|
+
if (!isMounted) return;
|
|
1772
|
+
const newLastSeen = payload.new?.last_seen_at ?? (/* @__PURE__ */ new Date()).toISOString();
|
|
1773
|
+
setLastSeen(newLastSeen);
|
|
1774
|
+
setStatus(calculateStatus(false, newLastSeen));
|
|
1775
|
+
}
|
|
1776
|
+
).subscribe();
|
|
1777
|
+
return () => {
|
|
1778
|
+
isMounted = false;
|
|
1779
|
+
supabase.removeChannel(channel);
|
|
1780
|
+
};
|
|
1781
|
+
}, [userId, initialLastSeenAt, currentAuthUserId]);
|
|
1782
|
+
return {
|
|
1783
|
+
status,
|
|
1784
|
+
isOnline: status === "online",
|
|
1785
|
+
lastSeen
|
|
1786
|
+
};
|
|
1787
|
+
};
|
|
1788
|
+
|
|
1698
1789
|
// src/hooks/index.ts
|
|
1699
1790
|
var Hooks = {
|
|
1700
|
-
useDebounce
|
|
1791
|
+
useDebounce,
|
|
1792
|
+
useUserStatus
|
|
1701
1793
|
};
|
|
1702
1794
|
export {
|
|
1703
1795
|
AIProvider,
|
|
@@ -1717,6 +1809,7 @@ export {
|
|
|
1717
1809
|
TranslationEditProvider,
|
|
1718
1810
|
UI,
|
|
1719
1811
|
UserSettingsProvider,
|
|
1812
|
+
defaultUserSettings,
|
|
1720
1813
|
useAI,
|
|
1721
1814
|
useAppSettings,
|
|
1722
1815
|
useAppTheme,
|