ajout app

This commit is contained in:
2024-04-17 20:22:30 +02:00
parent cc017cfc5e
commit f9d05a2fd3
8025 changed files with 729805 additions and 0 deletions

View File

@@ -0,0 +1,204 @@
import { useCallback, useState } from 'react'
import { useLocation, useNavigate, useParams } from 'react-router-dom'
import {
Button,
IconButton,
Menu,
MenuButton,
MenuItem,
MenuList,
Portal,
Table,
Tbody,
Td,
Th,
Thead,
Tr,
useToast,
} from '@chakra-ui/react'
import cx from 'classnames'
import { Helmet } from 'react-helmet-async'
import InvitationAPI, { SortBy, SortOrder } from '@/client/api/invitation'
import OrganizationAPI from '@/client/api/organization'
import { geEditorPermission } from '@/client/api/permission'
import { swrConfig } from '@/client/options'
import OrganizationInviteMembers from '@/components/organization/organization-invite-members'
import OrganizationStatus from '@/components/organization/organization-status'
import prettyDate from '@/helpers/pretty-date'
import { outgoingInvitationPaginationStorage } from '@/infra/pagination'
import {
IconMoreVert,
IconSend,
IconDelete,
IconPersonAdd,
SectionSpinner,
PagePagination,
usePagePagination,
} from '@/lib'
const OrganizationInvitationsPage = () => {
const navigate = useNavigate()
const location = useLocation()
const { id } = useParams()
const toast = useToast()
const { data: org, error: orgError } = OrganizationAPI.useGetById(
id,
swrConfig(),
)
const { page, size, steps, setPage, setSize } = usePagePagination({
navigate,
location,
storage: outgoingInvitationPaginationStorage(),
})
const {
data: list,
error: invitationsError,
mutate,
} = InvitationAPI.useGetOutgoing(
{
organizationId: id,
page,
size,
sortBy: SortBy.DateCreated,
sortOrder: SortOrder.Desc,
},
swrConfig(),
)
const [isInviteMembersModalOpen, setIsInviteMembersModalOpen] =
useState(false)
const handleResend = useCallback(
async (invitationId: string) => {
await InvitationAPI.resend(invitationId)
toast({
title: 'Invitation resent',
status: 'success',
isClosable: true,
})
},
[toast],
)
const handleDelete = useCallback(
async (invitationId: string) => {
await InvitationAPI.delete(invitationId)
mutate()
},
[mutate],
)
if (invitationsError || orgError) {
return null
}
if (!list || !org) {
return <SectionSpinner />
}
return (
<>
<Helmet>
<title>{org.name}</title>
</Helmet>
{list && list.data.length === 0 ? (
<>
<div
className={cx(
'flex',
'items-center',
'justify-center',
'h-[300px]',
)}
>
<div className={cx('flex', 'flex-col', 'gap-1.5', 'items-center')}>
<span>This organization has no invitations.</span>
{geEditorPermission(org.permission) && (
<Button
leftIcon={<IconPersonAdd />}
onClick={() => {
setIsInviteMembersModalOpen(true)
}}
>
Invite Members
</Button>
)}
</div>
</div>
<OrganizationInviteMembers
open={isInviteMembersModalOpen}
id={org.id}
onClose={() => setIsInviteMembersModalOpen(false)}
/>
</>
) : null}
{list && list.data.length > 0 ? (
<div className={cx('flex', 'flex-col', 'gap-3.5', 'py-3.5')}>
<Table variant="simple">
<Thead>
<Tr>
<Th>Email</Th>
<Th>Status</Th>
<Th>Date</Th>
<Th></Th>
</Tr>
</Thead>
<Tbody>
{list.data.map((i) => (
<Tr key={i.id}>
<Td>{i.email}</Td>
<Td>
<OrganizationStatus value={i.status} />
</Td>
<Td>{prettyDate(i.createTime)}</Td>
<Td className={cx('text-right')}>
<Menu>
<MenuButton
as={IconButton}
icon={<IconMoreVert />}
variant="ghost"
aria-label=""
/>
<Portal>
<MenuList>
{i.status === 'pending' && (
<MenuItem
icon={<IconSend />}
onClick={() => handleResend(i.id)}
>
Resend
</MenuItem>
)}
<MenuItem
icon={<IconDelete />}
className={cx('text-red-500')}
onClick={() => handleDelete(i.id)}
>
Delete
</MenuItem>
</MenuList>
</Portal>
</Menu>
</Td>
</Tr>
))}
</Tbody>
</Table>
{list && (
<PagePagination
style={{ alignSelf: 'end' }}
totalElements={list.totalElements}
totalPages={list.totalPages}
page={page}
size={size}
steps={steps}
setPage={setPage}
setSize={setSize}
/>
)}
</div>
) : null}
</>
)
}
export default OrganizationInvitationsPage