@serhii.olishevskyi/docs 1.1.2 → 1.1.4

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.
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  UserPopoverComponent,
3
3
  UserPopoverComponent_default
4
- } from "./chunk-BAFKGCJJ.mjs";
4
+ } from "./chunk-ERXHWCQ5.mjs";
5
5
  export {
6
6
  UserPopoverComponent,
7
7
  UserPopoverComponent_default as default
@@ -200,6 +200,84 @@ var getDeviceId = () => {
200
200
  };
201
201
 
202
202
  // src/services/session.service.ts
203
+ var fetchCompanySessions = async (supabase, companyId, page = 1, pageSize = 5, searchQuery = "") => {
204
+ const currentDeviceId = getDeviceId();
205
+ let query = supabase.from("memberships").select(`
206
+ user_id,
207
+ role,
208
+ employee_post,
209
+ profiles (
210
+ id,
211
+ display_name,
212
+ first_name,
213
+ last_name
214
+ )
215
+ `, { count: "exact" }).eq("company_id", companyId);
216
+ if (searchQuery.trim()) {
217
+ const q = `%${searchQuery.trim()}%`;
218
+ const { data: matchedProfiles } = await supabase.from("profiles").select("id").or(`display_name.ilike.${q},first_name.ilike.${q},last_name.ilike.${q}`);
219
+ const matchedUserIds = (matchedProfiles || []).map((p) => p.id);
220
+ if (matchedUserIds.length > 0) {
221
+ query = query.or(`employee_post.ilike.${q},user_id.in.(${matchedUserIds.join(",")})`);
222
+ } else {
223
+ query = query.ilike("employee_post", q);
224
+ }
225
+ }
226
+ const { data: members, error: membersError } = await query;
227
+ if (membersError) throw membersError;
228
+ if (!members || members.length === 0) {
229
+ return { data: [], totalCount: 0 };
230
+ }
231
+ const userMap = /* @__PURE__ */ new Map();
232
+ members.forEach((m) => {
233
+ const profile = Array.isArray(m.profiles) ? m.profiles[0] : m.profiles;
234
+ const name = profile?.display_name || [profile?.first_name, profile?.last_name].filter(Boolean).join(" ") || "\u041D\u0435\u0432\u0456\u0434\u043E\u043C\u0438\u0439 \u043A\u043E\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447";
235
+ userMap.set(m.user_id, {
236
+ name,
237
+ post: m.employee_post || "\u041F\u043E\u0441\u0430\u0434\u0430 \u043D\u0435 \u0432\u043A\u0430\u0437\u0430\u043D\u0430",
238
+ role: m.role || "user"
239
+ });
240
+ });
241
+ const userIds = Array.from(userMap.keys());
242
+ const { data: sessions, error: sessionsError } = await supabase.from("user_sessions").select("*").in("user_id", userIds).order("last_seen_at", { ascending: false });
243
+ if (sessionsError) throw sessionsError;
244
+ const groupsMap = /* @__PURE__ */ new Map();
245
+ (sessions || []).forEach((s) => {
246
+ const userInfo = userMap.get(s.user_id);
247
+ if (!userInfo) return;
248
+ if (!groupsMap.has(s.user_id)) {
249
+ groupsMap.set(s.user_id, {
250
+ userId: s.user_id,
251
+ userName: userInfo.name,
252
+ employeePost: userInfo.post,
253
+ role: userInfo.role,
254
+ sessions: []
255
+ });
256
+ }
257
+ groupsMap.get(s.user_id).sessions.push({
258
+ id: s.id,
259
+ user_id: s.user_id,
260
+ user_agent: s.user_agent,
261
+ ip_address: s.ip_address,
262
+ created_at: s.created_at,
263
+ last_seen_at: s.last_seen_at,
264
+ device_id: s.device_id,
265
+ is_current: s.device_id === currentDeviceId,
266
+ user_name: userInfo.name,
267
+ employee_post: userInfo.post,
268
+ role: userInfo.role,
269
+ url: s.url
270
+ });
271
+ });
272
+ const allGroupedWithSessions = Array.from(groupsMap.values()).filter((group) => group.sessions.length > 0).sort((a, b) => a.userName.localeCompare(b.userName, "uk"));
273
+ const totalCount = allGroupedWithSessions.length;
274
+ const from = (page - 1) * pageSize;
275
+ const paginatedData = allGroupedWithSessions.slice(from, from + pageSize);
276
+ return {
277
+ data: paginatedData,
278
+ totalCount
279
+ };
280
+ };
203
281
  var trackUserSession = async (supabase, userId) => {
204
282
  const deviceId = getDeviceId();
205
283
  let ip = "";
@@ -222,6 +300,17 @@ var trackUserSession = async (supabase, userId) => {
222
300
  { onConflict: "user_id, device_id" }
223
301
  );
224
302
  };
303
+ var fetchUserSessions = async (supabase) => {
304
+ const currentDeviceId = getDeviceId();
305
+ const { data: { user } } = await supabase.auth.getUser();
306
+ if (!user) return [];
307
+ const { data, error } = await supabase.from("user_sessions").select("*").eq("user_id", user.id).order("last_seen_at", { ascending: false });
308
+ if (error) throw error;
309
+ return (data || []).map((s) => ({
310
+ ...s,
311
+ is_current: s.device_id === currentDeviceId
312
+ }));
313
+ };
225
314
  var isCurrentSessionValid = async (supabase, userId) => {
226
315
  try {
227
316
  const currentDeviceId = getDeviceId();
@@ -237,11 +326,42 @@ var isCurrentSessionValid = async (supabase, userId) => {
237
326
  return true;
238
327
  }
239
328
  };
329
+ var groupSessionsByUser = (sessions) => {
330
+ const groupsMap = /* @__PURE__ */ new Map();
331
+ sessions.forEach((session) => {
332
+ const userId = session.user_id;
333
+ if (!groupsMap.has(userId)) {
334
+ groupsMap.set(userId, {
335
+ userId,
336
+ userName: session.user_name || "\u041D\u0435\u0432\u0456\u0434\u043E\u043C\u0438\u0439 \u043A\u043E\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447",
337
+ employeePost: session.employee_post || "\u041F\u043E\u0441\u0430\u0434\u0430 \u043D\u0435 \u0432\u043A\u0430\u0437\u0430\u043D\u0430",
338
+ role: session.role || "user",
339
+ sessions: []
340
+ });
341
+ }
342
+ groupsMap.get(userId).sessions.push(session);
343
+ });
344
+ return Array.from(groupsMap.values()).sort(
345
+ (a, b) => a.userName.localeCompare(b.userName, "uk")
346
+ );
347
+ };
240
348
  var getUserLastSeenAt = async (supabase, userId) => {
241
349
  const { data, error } = await supabase.from("user_sessions").select("last_seen_at").eq("user_id", userId).order("last_seen_at", { ascending: false }).limit(1).maybeSingle();
242
350
  if (error || !data) return null;
243
351
  return data.last_seen_at;
244
352
  };
353
+ var getUsersLastSeenMap = async (supabase, userIds) => {
354
+ if (!userIds.length) return {};
355
+ const { data, error } = await supabase.from("user_sessions").select("user_id, last_seen_at").in("user_id", userIds).order("last_seen_at", { ascending: false });
356
+ if (error || !data) return {};
357
+ const resultMap = {};
358
+ for (const session of data) {
359
+ if (!resultMap[session.user_id]) {
360
+ resultMap[session.user_id] = session.last_seen_at;
361
+ }
362
+ }
363
+ return resultMap;
364
+ };
245
365
 
246
366
  // src/context/AuthProvider.tsx
247
367
  import { jsx as jsx3 } from "react/jsx-runtime";
@@ -2413,6 +2533,13 @@ var UserPopoverComponent = ({
2413
2533
  var UserPopoverComponent_default = UserPopoverComponent;
2414
2534
 
2415
2535
  export {
2536
+ fetchCompanySessions,
2537
+ trackUserSession,
2538
+ fetchUserSessions,
2539
+ isCurrentSessionValid,
2540
+ groupSessionsByUser,
2541
+ getUserLastSeenAt,
2542
+ getUsersLastSeenMap,
2416
2543
  SupabaseProvider,
2417
2544
  useSupabase,
2418
2545
  AuthProvider,
package/dist/index.d.mts CHANGED
@@ -1,6 +1,7 @@
1
1
  import * as React$1 from 'react';
2
2
  import React__default, { ReactNode } from 'react';
3
3
  import { TextFieldProps, IconButtonProps, TooltipProps, SxProps, Theme } from '@mui/material';
4
+ import * as _supabase_supabase_js from '@supabase/supabase-js';
4
5
  import { SupabaseClient, User, Session } from '@supabase/supabase-js';
5
6
 
6
7
  interface UrlValue {
@@ -182,6 +183,14 @@ interface UserStatusChipComponentProps {
182
183
  };
183
184
  }
184
185
 
186
+ interface MyAvatarComponentProps {
187
+ size?: number;
188
+ disableBorder?: boolean;
189
+ disableShadow?: boolean;
190
+ disablePopover?: boolean;
191
+ sx?: SxProps<Theme>;
192
+ }
193
+
185
194
  declare const UI: {
186
195
  Inputs: {
187
196
  TextField: React$1.FC<TextFieldComponentProps>;
@@ -198,6 +207,11 @@ declare const UI: {
198
207
  UserPopover: React$1.FC<UserPopoverComponentProps>;
199
208
  UserRoleChip: React$1.FC<UserRoleChipComponentProps>;
200
209
  UserStatusChip: React$1.FC<UserStatusChipComponentProps>;
210
+ MyAvatar: React$1.FC<MyAvatarComponentProps>;
211
+ };
212
+ Widgets: {
213
+ ProtectedLanguageSelector: React$1.FC<{}>;
214
+ PublicLanguageSelector: React$1.FC<{}>;
201
215
  };
202
216
  };
203
217
 
@@ -475,4 +489,42 @@ declare const Providers: {
475
489
  readonly AIProvider: React$1.FC<AIProviderProps>;
476
490
  };
477
491
 
478
- export { type AIConfig, type AIGenerateOptions, AIProvider, type AIProviderProps, type AIProviderType, AppSettingsProvider, AuthProvider, BreadcrumbProvider, type ConfirmOptions, type ConfirmResult, ConfirmationProvider, type ConfirmationProviderProps, type CopyClipboardButtonComponentProps as CopyClipboardButtonProps, type DialogSeverity, type DisplayState, type EmailInputComponentProps as EmailInputProps, type Language, LocalizationProvider, type NumberInputComponentProps as NumberInputProps, Providers, type SupabaseConfig, SupabaseProvider, type SupabaseProviderProps, type TextFieldComponentProps as TextFieldProps, type ThemeColors, type ThemeConfig, type ThemeMode, ThemeProvider, ToastProvider, type ToastType, type TranslatableTooltipComponentProps as TranslatableTooltipProps, TranslateProvider, TranslateText, TranslationEditProvider, type TypographyConfig, UI, type UrlComponentProps as UrlProps, type UserAvatarComponentProps as UserAvatarProps, type UserPopoverComponentProps as UserPopoverProps, type UserRoleChipComponentProps as UserRoleChipProps, UserSettingsProvider, type UserStatusChipComponentProps as UserStatusChipProps, useAI, useAppSettings, useAppTheme, useAuth, useBreadcrumb, useConfirmation, useLocalization, useSupabase, useToast, useTranslationEdit, useTranslationNamespace, useUserSettings };
492
+ interface UserSessionItem {
493
+ id: string;
494
+ user_id: string;
495
+ user_agent: string | null;
496
+ ip_address: string | null;
497
+ created_at: string;
498
+ last_seen_at: string;
499
+ device_id: string;
500
+ url?: string | null;
501
+ is_current?: boolean;
502
+ user_name?: string;
503
+ employee_post?: string;
504
+ role?: string;
505
+ }
506
+ interface UserGroupedSessions {
507
+ userId: string;
508
+ userName: string;
509
+ employeePost: string;
510
+ role: string;
511
+ sessions: UserSessionItem[];
512
+ }
513
+ interface FetchCompanySessionsResponse {
514
+ data: UserGroupedSessions[];
515
+ totalCount: number;
516
+ }
517
+
518
+ declare const Services: {
519
+ readonly SessionService: {
520
+ readonly fetchCompanySessions: (supabase: _supabase_supabase_js.SupabaseClient, companyId: string, page?: number, pageSize?: number, searchQuery?: string) => Promise<FetchCompanySessionsResponse>;
521
+ readonly trackUserSession: (supabase: _supabase_supabase_js.SupabaseClient, userId: string) => Promise<void>;
522
+ readonly fetchUserSessions: (supabase: _supabase_supabase_js.SupabaseClient) => Promise<UserSessionItem[]>;
523
+ readonly isCurrentSessionValid: (supabase: _supabase_supabase_js.SupabaseClient, userId: string) => Promise<boolean>;
524
+ readonly groupSessionsByUser: (sessions: UserSessionItem[]) => UserGroupedSessions[];
525
+ readonly getUserLastSeenAt: (supabase: _supabase_supabase_js.SupabaseClient, userId: string) => Promise<string | null>;
526
+ readonly getUsersLastSeenMap: (supabase: _supabase_supabase_js.SupabaseClient, userIds: string[]) => Promise<Record<string, string>>;
527
+ };
528
+ };
529
+
530
+ export { type AIConfig, type AIGenerateOptions, AIProvider, type AIProviderProps, type AIProviderType, AppSettingsProvider, AuthProvider, BreadcrumbProvider, type ConfirmOptions, type ConfirmResult, ConfirmationProvider, type ConfirmationProviderProps, type CopyClipboardButtonComponentProps as CopyClipboardButtonProps, type DialogSeverity, type DisplayState, type EmailInputComponentProps as EmailInputProps, type Language, LocalizationProvider, type MyAvatarComponentProps as MyAvatarProps, type NumberInputComponentProps as NumberInputProps, Providers, Services, type SupabaseConfig, SupabaseProvider, type SupabaseProviderProps, type TextFieldComponentProps as TextFieldProps, type ThemeColors, type ThemeConfig, type ThemeMode, ThemeProvider, ToastProvider, type ToastType, type TranslatableTooltipComponentProps as TranslatableTooltipProps, TranslateProvider, TranslateText, TranslationEditProvider, type TypographyConfig, UI, type UrlComponentProps as UrlProps, type UserAvatarComponentProps as UserAvatarProps, type UserGroupedSessions, type UserPopoverComponentProps as UserPopoverProps, type UserRoleChipComponentProps as UserRoleChipProps, type UserSessionItem, UserSettingsProvider, type UserStatusChipComponentProps as UserStatusChipProps, useAI, useAppSettings, useAppTheme, useAuth, useBreadcrumb, useConfirmation, useLocalization, useSupabase, useToast, useTranslationEdit, useTranslationNamespace, useUserSettings };
package/dist/index.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import * as React$1 from 'react';
2
2
  import React__default, { ReactNode } from 'react';
3
3
  import { TextFieldProps, IconButtonProps, TooltipProps, SxProps, Theme } from '@mui/material';
4
+ import * as _supabase_supabase_js from '@supabase/supabase-js';
4
5
  import { SupabaseClient, User, Session } from '@supabase/supabase-js';
5
6
 
6
7
  interface UrlValue {
@@ -182,6 +183,14 @@ interface UserStatusChipComponentProps {
182
183
  };
183
184
  }
184
185
 
186
+ interface MyAvatarComponentProps {
187
+ size?: number;
188
+ disableBorder?: boolean;
189
+ disableShadow?: boolean;
190
+ disablePopover?: boolean;
191
+ sx?: SxProps<Theme>;
192
+ }
193
+
185
194
  declare const UI: {
186
195
  Inputs: {
187
196
  TextField: React$1.FC<TextFieldComponentProps>;
@@ -198,6 +207,11 @@ declare const UI: {
198
207
  UserPopover: React$1.FC<UserPopoverComponentProps>;
199
208
  UserRoleChip: React$1.FC<UserRoleChipComponentProps>;
200
209
  UserStatusChip: React$1.FC<UserStatusChipComponentProps>;
210
+ MyAvatar: React$1.FC<MyAvatarComponentProps>;
211
+ };
212
+ Widgets: {
213
+ ProtectedLanguageSelector: React$1.FC<{}>;
214
+ PublicLanguageSelector: React$1.FC<{}>;
201
215
  };
202
216
  };
203
217
 
@@ -475,4 +489,42 @@ declare const Providers: {
475
489
  readonly AIProvider: React$1.FC<AIProviderProps>;
476
490
  };
477
491
 
478
- export { type AIConfig, type AIGenerateOptions, AIProvider, type AIProviderProps, type AIProviderType, AppSettingsProvider, AuthProvider, BreadcrumbProvider, type ConfirmOptions, type ConfirmResult, ConfirmationProvider, type ConfirmationProviderProps, type CopyClipboardButtonComponentProps as CopyClipboardButtonProps, type DialogSeverity, type DisplayState, type EmailInputComponentProps as EmailInputProps, type Language, LocalizationProvider, type NumberInputComponentProps as NumberInputProps, Providers, type SupabaseConfig, SupabaseProvider, type SupabaseProviderProps, type TextFieldComponentProps as TextFieldProps, type ThemeColors, type ThemeConfig, type ThemeMode, ThemeProvider, ToastProvider, type ToastType, type TranslatableTooltipComponentProps as TranslatableTooltipProps, TranslateProvider, TranslateText, TranslationEditProvider, type TypographyConfig, UI, type UrlComponentProps as UrlProps, type UserAvatarComponentProps as UserAvatarProps, type UserPopoverComponentProps as UserPopoverProps, type UserRoleChipComponentProps as UserRoleChipProps, UserSettingsProvider, type UserStatusChipComponentProps as UserStatusChipProps, useAI, useAppSettings, useAppTheme, useAuth, useBreadcrumb, useConfirmation, useLocalization, useSupabase, useToast, useTranslationEdit, useTranslationNamespace, useUserSettings };
492
+ interface UserSessionItem {
493
+ id: string;
494
+ user_id: string;
495
+ user_agent: string | null;
496
+ ip_address: string | null;
497
+ created_at: string;
498
+ last_seen_at: string;
499
+ device_id: string;
500
+ url?: string | null;
501
+ is_current?: boolean;
502
+ user_name?: string;
503
+ employee_post?: string;
504
+ role?: string;
505
+ }
506
+ interface UserGroupedSessions {
507
+ userId: string;
508
+ userName: string;
509
+ employeePost: string;
510
+ role: string;
511
+ sessions: UserSessionItem[];
512
+ }
513
+ interface FetchCompanySessionsResponse {
514
+ data: UserGroupedSessions[];
515
+ totalCount: number;
516
+ }
517
+
518
+ declare const Services: {
519
+ readonly SessionService: {
520
+ readonly fetchCompanySessions: (supabase: _supabase_supabase_js.SupabaseClient, companyId: string, page?: number, pageSize?: number, searchQuery?: string) => Promise<FetchCompanySessionsResponse>;
521
+ readonly trackUserSession: (supabase: _supabase_supabase_js.SupabaseClient, userId: string) => Promise<void>;
522
+ readonly fetchUserSessions: (supabase: _supabase_supabase_js.SupabaseClient) => Promise<UserSessionItem[]>;
523
+ readonly isCurrentSessionValid: (supabase: _supabase_supabase_js.SupabaseClient, userId: string) => Promise<boolean>;
524
+ readonly groupSessionsByUser: (sessions: UserSessionItem[]) => UserGroupedSessions[];
525
+ readonly getUserLastSeenAt: (supabase: _supabase_supabase_js.SupabaseClient, userId: string) => Promise<string | null>;
526
+ readonly getUsersLastSeenMap: (supabase: _supabase_supabase_js.SupabaseClient, userIds: string[]) => Promise<Record<string, string>>;
527
+ };
528
+ };
529
+
530
+ export { type AIConfig, type AIGenerateOptions, AIProvider, type AIProviderProps, type AIProviderType, AppSettingsProvider, AuthProvider, BreadcrumbProvider, type ConfirmOptions, type ConfirmResult, ConfirmationProvider, type ConfirmationProviderProps, type CopyClipboardButtonComponentProps as CopyClipboardButtonProps, type DialogSeverity, type DisplayState, type EmailInputComponentProps as EmailInputProps, type Language, LocalizationProvider, type MyAvatarComponentProps as MyAvatarProps, type NumberInputComponentProps as NumberInputProps, Providers, Services, type SupabaseConfig, SupabaseProvider, type SupabaseProviderProps, type TextFieldComponentProps as TextFieldProps, type ThemeColors, type ThemeConfig, type ThemeMode, ThemeProvider, ToastProvider, type ToastType, type TranslatableTooltipComponentProps as TranslatableTooltipProps, TranslateProvider, TranslateText, TranslationEditProvider, type TypographyConfig, UI, type UrlComponentProps as UrlProps, type UserAvatarComponentProps as UserAvatarProps, type UserGroupedSessions, type UserPopoverComponentProps as UserPopoverProps, type UserRoleChipComponentProps as UserRoleChipProps, type UserSessionItem, UserSettingsProvider, type UserStatusChipComponentProps as UserStatusChipProps, useAI, useAppSettings, useAppTheme, useAuth, useBreadcrumb, useConfirmation, useLocalization, useSupabase, useToast, useTranslationEdit, useTranslationNamespace, useUserSettings };