From 8f3c0dd21689887ef4ea56cf95f438eb93ea9667 Mon Sep 17 00:00:00 2001 From: Mateusz Baginski Date: Sun, 29 Dec 2024 17:18:12 +0100 Subject: [PATCH] feat(chat): groups management works --- apps/chat/src/i18n/packs/i18n-lang-en.ts | 5 +- apps/chat/src/i18n/packs/i18n-lang-pl.ts | 5 +- .../apps/choose-app/choose-app-modal.tsx | 31 ++---- .../src/modules/shared/ghost-placeholder.tsx | 16 ++- .../modules/users-groups/form/create/types.ts | 5 + .../create/use-users-group-create-form.tsx | 8 +- .../create/use-users-group-create-modal.tsx | 6 +- .../create/users-group-create-form-modal.tsx | 6 +- .../form/shared/group-users-select-table.tsx | 99 +++++++++++++++++++ .../modules/users-groups/form/shared/index.ts | 1 + .../shared/users-group-shared-form-fields.tsx | 32 +++--- .../users/choose-users/choose-users-modal.tsx | 85 ++++++++++++++++ .../src/modules/users/choose-users/index.ts | 2 + .../choose-users/use-choose-users-modal.tsx | 27 +++++ apps/chat/src/modules/users/index.ts | 1 + .../users/table/users-table-container.tsx | 11 ++- .../modules/users/table/users-table-row.tsx | 49 ++++----- .../ui/src/components/list/paginated-list.tsx | 2 +- .../predefined/buttons/add-button.tsx | 20 ++++ .../predefined/buttons/archive-button.tsx | 2 +- .../predefined/buttons/create-button.tsx | 11 ++- .../predefined/buttons/delete-button.tsx | 2 +- .../components/predefined/buttons/index.ts | 2 + .../predefined/buttons/save-button.tsx | 10 +- .../buttons/select-record-button.tsx | 37 +++++++ .../predefined/buttons/unarchive-button.tsx | 2 +- .../predefined/buttons/update-button.tsx | 2 +- .../src/components/table/paginated-table.tsx | 10 +- .../src/i18n/packs/i18n-forwarded-en-pack.tsx | 2 + .../src/i18n/packs/i18n-forwarded-pl-pack.tsx | 2 + 30 files changed, 402 insertions(+), 91 deletions(-) create mode 100644 apps/chat/src/modules/users-groups/form/create/types.ts create mode 100644 apps/chat/src/modules/users-groups/form/shared/group-users-select-table.tsx create mode 100644 apps/chat/src/modules/users/choose-users/choose-users-modal.tsx create mode 100644 apps/chat/src/modules/users/choose-users/index.ts create mode 100644 apps/chat/src/modules/users/choose-users/use-choose-users-modal.tsx create mode 100644 packages/ui/src/components/predefined/buttons/add-button.tsx create mode 100644 packages/ui/src/components/predefined/buttons/select-record-button.tsx diff --git a/apps/chat/src/i18n/packs/i18n-lang-en.ts b/apps/chat/src/i18n/packs/i18n-lang-en.ts index 417de0d3..7f96db58 100644 --- a/apps/chat/src/i18n/packs/i18n-lang-en.ts +++ b/apps/chat/src/i18n/packs/i18n-lang-en.ts @@ -291,8 +291,6 @@ export const I18N_PACK_EN = deepmerge(I18N_FORWARDED_EN_PACK, { }, chooseAppModal: { title: 'Choose App', - select: 'Select', - selected: 'Selected', }, }, appsCreator: { @@ -444,6 +442,9 @@ export const I18N_PACK_EN = deepmerge(I18N_FORWARDED_EN_PACK, { email: 'Email', }, }, + chooseUsersModal: { + title: 'Choose users', + }, }, usersGroups: { form: { diff --git a/apps/chat/src/i18n/packs/i18n-lang-pl.ts b/apps/chat/src/i18n/packs/i18n-lang-pl.ts index 73596cd3..a876107b 100644 --- a/apps/chat/src/i18n/packs/i18n-lang-pl.ts +++ b/apps/chat/src/i18n/packs/i18n-lang-pl.ts @@ -293,8 +293,6 @@ export const I18N_PACK_PL: I18nLangPack = deepmerge(I18N_FORWARDED_PL_PACK, { }, chooseAppModal: { title: 'Wybierz aplikację', - select: 'Wybierz', - selected: 'Wybrano', }, }, appsCreator: { @@ -446,6 +444,9 @@ export const I18N_PACK_PL: I18nLangPack = deepmerge(I18N_FORWARDED_PL_PACK, { password: 'Hasło', }, }, + chooseUsersModal: { + title: 'Wybierz użytkowników', + }, }, usersGroups: { form: { diff --git a/apps/chat/src/modules/apps/choose-app/choose-app-modal.tsx b/apps/chat/src/modules/apps/choose-app/choose-app-modal.tsx index fda475bc..bee551d2 100644 --- a/apps/chat/src/modules/apps/choose-app/choose-app-modal.tsx +++ b/apps/chat/src/modules/apps/choose-app/choose-app-modal.tsx @@ -1,7 +1,9 @@ +import { suppressEvent } from '@under-control/forms'; + import type { SdkAppT, SdkTableRowWithIdT } from '@llm/sdk'; import { findItemById } from '@llm/commons'; -import { Modal, type ModalProps, ModalTitle } from '@llm/ui'; +import { Modal, type ModalProps, ModalTitle, SelectRecordButton } from '@llm/ui'; import { useI18n } from '~/i18n'; import { AppsContainer } from '../grid'; @@ -22,31 +24,18 @@ export function ChooseAppModal({ const t = useI18n().pack.apps.chooseAppModal; const renderAppCTA = (app: SdkAppT) => { - if (findItemById(app.id)(selectedApps || [])) { - return ( - { - e.preventDefault(); - }} - > - {t.selected} - - ); - } + const installed = !!findItemById(app.id)(selectedApps || []); return ( - { - e.preventDefault(); + suppressEvent(e); onSelect?.(app); }} - > - {t.select} - + /> ); }; diff --git a/apps/chat/src/modules/shared/ghost-placeholder.tsx b/apps/chat/src/modules/shared/ghost-placeholder.tsx index e7a5beae..1c4c392c 100644 --- a/apps/chat/src/modules/shared/ghost-placeholder.tsx +++ b/apps/chat/src/modules/shared/ghost-placeholder.tsx @@ -1,10 +1,22 @@ import type { PropsWithChildren } from 'react'; +import clsx from 'clsx'; import { GhostIcon } from 'lucide-react'; -export function GhostPlaceholder({ children }: PropsWithChildren) { +type Props = PropsWithChildren & { + spaced?: boolean; + className?: string; +}; + +export function GhostPlaceholder({ children, className, spaced = true }: Props) { return ( -
+
diff --git a/apps/chat/src/modules/users-groups/form/create/types.ts b/apps/chat/src/modules/users-groups/form/create/types.ts new file mode 100644 index 00000000..e808f35e --- /dev/null +++ b/apps/chat/src/modules/users-groups/form/create/types.ts @@ -0,0 +1,5 @@ +import type { SdkCreateUsersGroupInputT, SdkUserListItemT } from '@llm/sdk'; + +export type CreateUsersGroupValue = Omit & { + users: SdkUserListItemT[]; +}; diff --git a/apps/chat/src/modules/users-groups/form/create/use-users-group-create-form.tsx b/apps/chat/src/modules/users-groups/form/create/use-users-group-create-form.tsx index 5b63d98a..b440c356 100644 --- a/apps/chat/src/modules/users-groups/form/create/use-users-group-create-form.tsx +++ b/apps/chat/src/modules/users-groups/form/create/use-users-group-create-form.tsx @@ -2,12 +2,14 @@ import { type FormHookAttrs, useForm } from '@under-control/forms'; import { flow } from 'fp-ts/lib/function'; import { runTask, tapTaskEither } from '@llm/commons'; -import { type SdkCreateUsersGroupInputT, useSdkForLoggedIn } from '@llm/sdk'; +import { useSdkForLoggedIn } from '@llm/sdk'; import { usePredefinedFormValidators, useSaveTaskEitherNotification } from '@llm/ui'; +import type { CreateUsersGroupValue } from './types'; + type CreateUsersGroupFormHookAttrs = & Omit< - FormHookAttrs, + FormHookAttrs, 'validation' | 'onSubmit' > & { @@ -21,7 +23,7 @@ export function useUsersGroupCreateForm( }: CreateUsersGroupFormHookAttrs, ) { const { sdks } = useSdkForLoggedIn(); - const { required, requiredListItem } = usePredefinedFormValidators(); + const { required, requiredListItem } = usePredefinedFormValidators(); const saveNotifications = useSaveTaskEitherNotification(); return useForm({ diff --git a/apps/chat/src/modules/users-groups/form/create/use-users-group-create-modal.tsx b/apps/chat/src/modules/users-groups/form/create/use-users-group-create-modal.tsx index 391d93e9..5b985d90 100644 --- a/apps/chat/src/modules/users-groups/form/create/use-users-group-create-modal.tsx +++ b/apps/chat/src/modules/users-groups/form/create/use-users-group-create-modal.tsx @@ -1,8 +1,8 @@ -import type { SdkCreateUsersGroupInputT } from '@llm/sdk'; - import { useAnimatedModal } from '@llm/commons-front'; import { useWorkspaceOrganizationOrThrow } from '~/modules/workspace'; +import type { CreateUsersGroupValue } from './types'; + import { UsersGroupCreateFormModal, type UsersGroupCreateFormModalProps, @@ -11,7 +11,7 @@ import { type UsersGroupShowModalProps = & Pick & { - defaultValue: Omit; + defaultValue: Omit; }; export function useUsersGroupCreateModal() { diff --git a/apps/chat/src/modules/users-groups/form/create/users-group-create-form-modal.tsx b/apps/chat/src/modules/users-groups/form/create/users-group-create-form-modal.tsx index 07d85bcc..f97fa66b 100644 --- a/apps/chat/src/modules/users-groups/form/create/users-group-create-form-modal.tsx +++ b/apps/chat/src/modules/users-groups/form/create/users-group-create-form-modal.tsx @@ -1,5 +1,3 @@ -import type { SdkCreateUsersGroupInputT } from '@llm/sdk'; - import { CancelButton, CreateButton, @@ -10,13 +8,15 @@ import { } from '@llm/ui'; import { useI18n } from '~/i18n'; +import type { CreateUsersGroupValue } from './types'; + import { UsersGroupSharedFormFields } from '../shared'; import { useUsersGroupCreateForm } from './use-users-group-create-form'; export type UsersGroupCreateFormModalProps = & Omit & { - defaultValue: SdkCreateUsersGroupInputT; + defaultValue: CreateUsersGroupValue; onAfterSubmit?: VoidFunction; }; diff --git a/apps/chat/src/modules/users-groups/form/shared/group-users-select-table.tsx b/apps/chat/src/modules/users-groups/form/shared/group-users-select-table.tsx new file mode 100644 index 00000000..90614e7f --- /dev/null +++ b/apps/chat/src/modules/users-groups/form/shared/group-users-select-table.tsx @@ -0,0 +1,99 @@ +import { controlled, useControlStrict } from '@under-control/forms'; +import { pipe } from 'fp-ts/lib/function'; + +import type { SdkOffsetPaginationInputT, SdkUserListItemT } from '@llm/sdk'; + +import { tapTaskOption } from '@llm/commons'; +import { useAsyncCallback } from '@llm/commons-front'; +import { AddButton, EllipsisCrudDropdownButton, FormField, PaginatedTable } from '@llm/ui'; +import { useI18n } from '~/i18n'; +import { GhostPlaceholder } from '~/modules/shared'; +import { useChooseUsersModal } from '~/modules/users/choose-users'; + +export const GroupUsersSelectTable = controlled(({ control: { value, setValue } }) => { + const { pack } = useI18n(); + const t = pack.table.columns; + + const pagination = useControlStrict({ + defaultValue: { + offset: 0, + limit: 10, + }, + }); + + const chooseUsersModal = useChooseUsersModal(); + + const [onShowChooseUsersModal, choosingUsersState] = useAsyncCallback( + pipe( + chooseUsersModal.showAsOptional({ + selectedUsers: value, + }), + tapTaskOption((users) => { + setValue({ + value: users, + }); + }), + ), + ); + + const paginationOutput = { + total: Math.min(value.length, pagination.value.limit), + items: value.slice( + pagination.value.offset, + pagination.value.offset + pagination.value.limit, + ), + }; + + return ( + + + + {value.length > 0 && ( + + {({ item }) => ( + + {item.id} + {item.email} + + { + setValue({ + value: value.filter(user => user.id !== item.id), + }); + }} + /> + + + )} + + )} + + {!value.length && ( + + )} + + ); +}); diff --git a/apps/chat/src/modules/users-groups/form/shared/index.ts b/apps/chat/src/modules/users-groups/form/shared/index.ts index 602de00e..f8daf433 100644 --- a/apps/chat/src/modules/users-groups/form/shared/index.ts +++ b/apps/chat/src/modules/users-groups/form/shared/index.ts @@ -1 +1,2 @@ +export * from './group-users-select-table'; export * from './users-group-shared-form-fields'; diff --git a/apps/chat/src/modules/users-groups/form/shared/users-group-shared-form-fields.tsx b/apps/chat/src/modules/users-groups/form/shared/users-group-shared-form-fields.tsx index 2badb2ad..b8731c57 100644 --- a/apps/chat/src/modules/users-groups/form/shared/users-group-shared-form-fields.tsx +++ b/apps/chat/src/modules/users-groups/form/shared/users-group-shared-form-fields.tsx @@ -5,7 +5,9 @@ import type { SdkUsersGroupT } from '@llm/sdk'; import { FormField, Input } from '@llm/ui'; import { useI18n } from '~/i18n'; -type Value = Pick; +import { GroupUsersSelectTable } from './group-users-select-table'; + +type Value = Pick; type Props = ValidationErrorsListProps; @@ -14,17 +16,21 @@ export const UsersGroupSharedFormFields = controlled(({ errors, co const validation = useFormValidatorMessages({ errors }); return ( - - - + <> + + + + + + ); }); diff --git a/apps/chat/src/modules/users/choose-users/choose-users-modal.tsx b/apps/chat/src/modules/users/choose-users/choose-users-modal.tsx new file mode 100644 index 00000000..21eae4dc --- /dev/null +++ b/apps/chat/src/modules/users/choose-users/choose-users-modal.tsx @@ -0,0 +1,85 @@ +import { useControlStrict } from '@under-control/forms'; + +import type { SdkUserListItemT } from '@llm/sdk'; + +import { findItemById, rejectById } from '@llm/commons'; +import { Modal, type ModalProps, ModalTitle, SaveButton, SelectRecordButton } from '@llm/ui'; +import { useI18n } from '~/i18n'; + +import { UsersTableContainer } from '../table'; + +export type ChooseUsersModalProps = + & Omit + & { + selectedUsers?: SdkUserListItemT[]; + onSelected: (users: SdkUserListItemT[]) => void; + }; + +export function ChooseUsersModal( + { + selectedUsers, + onSelected, + onClose, + ...props + }: ChooseUsersModalProps, +) { + const t = useI18n().pack.users.chooseUsersModal; + const { value, setValue } = useControlStrict({ + defaultValue: selectedUsers || [], + }); + + const renderCTARowButton = (user: SdkUserListItemT) => { + const selected = !!findItemById(user.id)(value); + + return ( +
+ { + const rejectedUsers = rejectById(user.id)(value); + + if (selected) { + setValue({ value: rejectedUsers }); + } + else { + setValue({ value: [user, ...rejectedUsers] }); + } + }} + /> +
+ ); + }; + + return ( + + {t.title} + + )} + footer={( + { + onSelected(value); + }} + /> + )} + > + ({ + ctaButton: renderCTARowButton(item), + })} + /> + + ); +} diff --git a/apps/chat/src/modules/users/choose-users/index.ts b/apps/chat/src/modules/users/choose-users/index.ts new file mode 100644 index 00000000..63bb5aca --- /dev/null +++ b/apps/chat/src/modules/users/choose-users/index.ts @@ -0,0 +1,2 @@ +export * from './choose-users-modal'; +export * from './use-choose-users-modal'; diff --git a/apps/chat/src/modules/users/choose-users/use-choose-users-modal.tsx b/apps/chat/src/modules/users/choose-users/use-choose-users-modal.tsx new file mode 100644 index 00000000..d1b3ec51 --- /dev/null +++ b/apps/chat/src/modules/users/choose-users/use-choose-users-modal.tsx @@ -0,0 +1,27 @@ +import type { SdkUserListItemT } from '@llm/sdk'; + +import { useAnimatedModal } from '@llm/commons-front'; + +import { + ChooseUsersModal, + type ChooseUsersModalProps, +} from './choose-users-modal'; + +type ChooseUsersShowModalProps = Omit; + +export function useChooseUsersModal() { + return useAnimatedModal({ + renderModalContent: ({ showProps, hiding, onAnimatedClose }) => ( + { + void onAnimatedClose(users); + }} + onClose={() => { + void onAnimatedClose(); + }} + /> + ), + }); +} diff --git a/apps/chat/src/modules/users/index.ts b/apps/chat/src/modules/users/index.ts index b3eece8a..de6efddf 100644 --- a/apps/chat/src/modules/users/index.ts +++ b/apps/chat/src/modules/users/index.ts @@ -1,2 +1,3 @@ +export * from './choose-users'; export * from './form'; export * from './table'; diff --git a/apps/chat/src/modules/users/table/users-table-container.tsx b/apps/chat/src/modules/users/table/users-table-container.tsx index b68b13d4..f370c940 100644 --- a/apps/chat/src/modules/users/table/users-table-container.tsx +++ b/apps/chat/src/modules/users/table/users-table-container.tsx @@ -2,7 +2,7 @@ import { flow, pipe } from 'fp-ts/lib/function'; import { genRandomPassword, tapTaskOption } from '@llm/commons'; import { useAsyncCallback } from '@llm/commons-front'; -import { SdkSearchUsersInputV, useSdkForLoggedIn } from '@llm/sdk'; +import { type SdkSearchUserItemT, SdkSearchUsersInputV, useSdkForLoggedIn } from '@llm/sdk'; import { ArchiveFilterTabs, CreateButton, @@ -16,9 +16,13 @@ import { useI18n } from '~/i18n'; import { useWorkspaceOrganizationOrThrow } from '~/modules/workspace'; import { useUserCreateModal } from '../form'; -import { UsersTableRow } from './users-table-row'; +import { UsersTableRow, type UsersTableRowProps } from './users-table-row'; -export function UsersTableContainer() { +type Props = { + itemPropsFn?: (item: SdkSearchUserItemT) => Omit; +}; + +export function UsersTableContainer({ itemPropsFn }: Props) { const { pack } = useI18n(); const t = pack.table.columns; @@ -102,6 +106,7 @@ export function UsersTableContainer() { key={item.id} item={item} onUpdated={reload} + {...itemPropsFn?.(item)} /> )} diff --git a/apps/chat/src/modules/users/table/users-table-row.tsx b/apps/chat/src/modules/users/table/users-table-row.tsx index e833575a..c9b10147 100644 --- a/apps/chat/src/modules/users/table/users-table-row.tsx +++ b/apps/chat/src/modules/users/table/users-table-row.tsx @@ -1,3 +1,5 @@ +import type { ReactNode } from 'react'; + import { pipe } from 'fp-ts/lib/function'; import { KeyRoundIcon, MailIcon } from 'lucide-react'; @@ -9,12 +11,13 @@ import { OrganizationUserRoleBadge } from '~/modules/organizations'; import { useUserUpdateModal } from '../form'; -type Props = { +export type UsersTableRowProps = { item: SdkSearchUserItemT; + ctaButton?: ReactNode; onUpdated: VoidFunction; }; -export function UsersTableRow({ item, onUpdated }: Props) { +export function UsersTableRow({ item, ctaButton, onUpdated }: UsersTableRowProps) { const { pack } = useI18n(); const t = pack.users; @@ -53,28 +56,30 @@ export function UsersTableRow({ item, onUpdated }: Props) { {formatDate(item.updatedAt)} - + }} + /> + )} ); diff --git a/packages/ui/src/components/list/paginated-list.tsx b/packages/ui/src/components/list/paginated-list.tsx index 3055b11c..c68405c1 100644 --- a/packages/ui/src/components/list/paginated-list.tsx +++ b/packages/ui/src/components/list/paginated-list.tsx @@ -17,7 +17,7 @@ export type PaginatedListProps< I extends SdkTableRowWithIdT | SdkTableRowWithUuidT, P extends SdkOffsetPaginationInputT, > = { - loading: boolean; + loading?: boolean; withEmptyPlaceholder?: boolean; result?: SdkOffsetPaginationOutputT | null; pagination: ControlledControlStateAttrs

; diff --git a/packages/ui/src/components/predefined/buttons/add-button.tsx b/packages/ui/src/components/predefined/buttons/add-button.tsx new file mode 100644 index 00000000..00bffcd7 --- /dev/null +++ b/packages/ui/src/components/predefined/buttons/add-button.tsx @@ -0,0 +1,20 @@ +import { PlusIcon } from 'lucide-react'; + +import { FormSpinnerCTA, type FormSpinnerCTAProps } from '~/components/form'; +import { useForwardedI18n } from '~/i18n'; + +type Props = Omit; + +export function AddButton({ loading, ...props }: Props) { + const { pack } = useForwardedI18n(); + + return ( + + {!loading && ( + + )} + + {pack.buttons.add} + + ); +} diff --git a/packages/ui/src/components/predefined/buttons/archive-button.tsx b/packages/ui/src/components/predefined/buttons/archive-button.tsx index 3992d632..bca133c9 100644 --- a/packages/ui/src/components/predefined/buttons/archive-button.tsx +++ b/packages/ui/src/components/predefined/buttons/archive-button.tsx @@ -3,7 +3,7 @@ import { useForwardedI18n } from '~/i18n'; type Props = Omit; -export function ArchiveButton({ className, ...props }: Props) { +export function ArchiveButton(props: Props) { const { pack } = useForwardedI18n(); return ( diff --git a/packages/ui/src/components/predefined/buttons/create-button.tsx b/packages/ui/src/components/predefined/buttons/create-button.tsx index 050d66c0..6ace161a 100644 --- a/packages/ui/src/components/predefined/buttons/create-button.tsx +++ b/packages/ui/src/components/predefined/buttons/create-button.tsx @@ -3,15 +3,16 @@ import { PlusIcon } from 'lucide-react'; import { FormSpinnerCTA, type FormSpinnerCTAProps } from '~/components/form'; import { useForwardedI18n } from '~/i18n'; -type Props = Omit; +type Props = Omit & { + withIcon?: boolean; +}; -export function CreateButton({ className, ...props }: Props) { +export function CreateButton({ loading, withIcon = true, ...props }: Props) { const { pack } = useForwardedI18n(); return ( - - - + + {withIcon && !loading && } {pack.buttons.create} ); diff --git a/packages/ui/src/components/predefined/buttons/delete-button.tsx b/packages/ui/src/components/predefined/buttons/delete-button.tsx index 0f1c2d41..12927276 100644 --- a/packages/ui/src/components/predefined/buttons/delete-button.tsx +++ b/packages/ui/src/components/predefined/buttons/delete-button.tsx @@ -3,7 +3,7 @@ import { useForwardedI18n } from '~/i18n'; type Props = Omit; -export function DeleteButton({ className, ...props }: Props) { +export function DeleteButton(props: Props) { const { pack } = useForwardedI18n(); return ( diff --git a/packages/ui/src/components/predefined/buttons/index.ts b/packages/ui/src/components/predefined/buttons/index.ts index 71e1f525..36c3afc6 100644 --- a/packages/ui/src/components/predefined/buttons/index.ts +++ b/packages/ui/src/components/predefined/buttons/index.ts @@ -1,8 +1,10 @@ +export * from './add-button'; export * from './archive-button'; export * from './cancel-button'; export * from './create-button'; export * from './delete-button'; export * from './reset-filters-button'; export * from './save-button'; +export * from './select-record-button'; export * from './unarchive-button'; export * from './update-button'; diff --git a/packages/ui/src/components/predefined/buttons/save-button.tsx b/packages/ui/src/components/predefined/buttons/save-button.tsx index a2b0c7f8..696cad5e 100644 --- a/packages/ui/src/components/predefined/buttons/save-button.tsx +++ b/packages/ui/src/components/predefined/buttons/save-button.tsx @@ -3,14 +3,16 @@ import { SendIcon } from 'lucide-react'; import { FormSpinnerCTA, type FormSpinnerCTAProps } from '~/components/form'; import { useForwardedI18n } from '~/i18n'; -type Props = Omit; +type Props = Omit & { + withIcon?: boolean; +}; -export function SaveButton(props: Props) { +export function SaveButton({ loading, withIcon = true, ...props }: Props) { const { pack } = useForwardedI18n(); return ( - - + + {withIcon && !loading && } {pack.buttons.save} diff --git a/packages/ui/src/components/predefined/buttons/select-record-button.tsx b/packages/ui/src/components/predefined/buttons/select-record-button.tsx new file mode 100644 index 00000000..6dea3fd1 --- /dev/null +++ b/packages/ui/src/components/predefined/buttons/select-record-button.tsx @@ -0,0 +1,37 @@ +import type { ComponentProps } from 'react'; + +import clsx from 'clsx'; +import { CheckIcon } from 'lucide-react'; + +import { useForwardedI18n } from '~/i18n'; + +type Props = Omit, 'children'> & { + selected?: boolean; + disabled?: boolean; +}; + +export function SelectRecordButton({ className, disabled, selected, ...props }: Props) { + const t = useForwardedI18n().pack.buttons; + + return ( + + ); +} diff --git a/packages/ui/src/components/predefined/buttons/unarchive-button.tsx b/packages/ui/src/components/predefined/buttons/unarchive-button.tsx index e9be45d0..b0cd1479 100644 --- a/packages/ui/src/components/predefined/buttons/unarchive-button.tsx +++ b/packages/ui/src/components/predefined/buttons/unarchive-button.tsx @@ -3,7 +3,7 @@ import { useForwardedI18n } from '~/i18n'; type Props = Omit; -export function UnarchiveButton({ className, ...props }: Props) { +export function UnarchiveButton(props: Props) { const { pack } = useForwardedI18n(); return ( diff --git a/packages/ui/src/components/predefined/buttons/update-button.tsx b/packages/ui/src/components/predefined/buttons/update-button.tsx index 44ca3bab..854f9a73 100644 --- a/packages/ui/src/components/predefined/buttons/update-button.tsx +++ b/packages/ui/src/components/predefined/buttons/update-button.tsx @@ -3,7 +3,7 @@ import { useForwardedI18n } from '~/i18n'; type Props = Omit; -export function UpdateButton({ className, ...props }: Props) { +export function UpdateButton(props: Props) { const { pack } = useForwardedI18n(); return ( diff --git a/packages/ui/src/components/table/paginated-table.tsx b/packages/ui/src/components/table/paginated-table.tsx index dda6d293..6ed70d44 100644 --- a/packages/ui/src/components/table/paginated-table.tsx +++ b/packages/ui/src/components/table/paginated-table.tsx @@ -14,23 +14,27 @@ type Props< P extends SdkOffsetPaginationInputT, > = & Omit, 'items'> - & Omit, 'children'>; + & Omit, 'children'> + & { + spaced?: boolean; + }; export function PaginatedTable< I extends SdkTableRowWithIdT | SdkTableRowWithUuidT, P extends SdkOffsetPaginationInputT, ->({ result, loading, pagination, className, ...props }: Props) { +>({ result, loading = false, pagination, className, footerProps, spaced = true, ...props }: Props) { return ( {({ items }) => ( )} diff --git a/packages/ui/src/i18n/packs/i18n-forwarded-en-pack.tsx b/packages/ui/src/i18n/packs/i18n-forwarded-en-pack.tsx index b15d180f..2d78c4d0 100644 --- a/packages/ui/src/i18n/packs/i18n-forwarded-en-pack.tsx +++ b/packages/ui/src/i18n/packs/i18n-forwarded-en-pack.tsx @@ -45,6 +45,8 @@ export const I18N_FORWARDED_EN_PACK = { confirm: 'Confirm', resetFilters: 'Reset filters', download: 'Download', + select: 'Select', + selected: 'Selected', expand: { more: 'More', less: 'Less', diff --git a/packages/ui/src/i18n/packs/i18n-forwarded-pl-pack.tsx b/packages/ui/src/i18n/packs/i18n-forwarded-pl-pack.tsx index 6dbb3eb4..9d17a5b1 100644 --- a/packages/ui/src/i18n/packs/i18n-forwarded-pl-pack.tsx +++ b/packages/ui/src/i18n/packs/i18n-forwarded-pl-pack.tsx @@ -47,6 +47,8 @@ export const I18N_FORWARDED_PL_PACK: typeof I18N_FORWARDED_EN_PACK = { add: 'Dodaj', confirm: 'Potwierdź', download: 'Pobierz', + select: 'Wybierz', + selected: 'Wybrano', expand: { more: 'Więcej', less: 'Mniej',