Skip to content

Commit

Permalink
Merge pull request #80 from DISIC/feat/user-crud
Browse files Browse the repository at this point in the history
feat: users crud
  • Loading branch information
ClementNumericite authored Jan 26, 2024
2 parents a141450 + 985a69e commit e68611b
Show file tree
Hide file tree
Showing 11 changed files with 963 additions and 44 deletions.
109 changes: 109 additions & 0 deletions components/administration/UserCard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
import { OnButtonClickUserParams } from '@/pages/administration/bo/users';
import { formatDateToFrenchString } from '@/utils/tools';
import { fr } from '@codegouvfr/react-dsfr';
import Button from '@codegouvfr/react-dsfr/Button';
import { makeStyles } from '@codegouvfr/react-dsfr/tss';
import { Prisma, User } from '@prisma/client';
import { useSession } from 'next-auth/react';
import { Dispatch, SetStateAction } from 'react';

type Props = {
user: User;
modalProps: { onClick: () => void };
setCurrentUser: Dispatch<
SetStateAction<
(Prisma.UserUpdateInput & { id: string }) | Prisma.UserCreateInput
>
>;
onButtonClick: ({ type, user }: OnButtonClickUserParams) => void;
};

const UserCard = ({
user,
onButtonClick,
modalProps,
setCurrentUser
}: Props) => {
const { data: session } = useSession({ required: true });
const { cx, classes } = useStyles();

return (
<div className={fr.cx('fr-card', 'fr-my-3w', 'fr-p-2w')}>
<div
className={fr.cx(
'fr-grid-row',
'fr-grid-row--gutters',
'fr-grid-row--middle'
)}
>
<div className={fr.cx('fr-col', 'fr-col-12', 'fr-col-md-3')}>
<p className={cx(fr.cx('fr-mb-0'), classes.spanFullName)}>
{user.username}
</p>
<span className={classes.userEmail}>{user.email}</span>
</div>
<div className={fr.cx('fr-col', 'fr-col-12', 'fr-col-md-3')}>
{user.created_at ? (
<span>{formatDateToFrenchString(user.created_at.toString())}</span>
) : (
'x'
)}
</div>
<div
className={cx(
fr.cx('fr-col', 'fr-col-12', 'fr-col-md-4'),
classes.wrapperButtons
)}
>
<Button
priority="tertiary"
size="small"
iconId="fr-icon-delete-bin-line"
disabled={session?.user?.email === user.email}
iconPosition="right"
className={cx(fr.cx('fr-mr-5v'), classes.iconError)}
onClick={() => onButtonClick({ type: 'delete', user })}
>
Supprimer
</Button>
<div
onClick={() => {
setCurrentUser(user);
}}
>
<Button
priority="secondary"
size="small"
iconId="fr-icon-edit-line"
iconPosition="right"
{...modalProps}
>
Modifier
</Button>
</div>
</div>
</div>
</div>
);
};

const useStyles = makeStyles()(theme => ({
spanFullName: {
fontWeight: 'bold'
},
iconSuccess: {
color: 'green'
},
iconError: {
color: theme.decisions.text.default.error.default
},
wrapperButtons: {
display: 'flex',
justifyContent: 'end'
},
userEmail: {
wordWrap: 'break-word'
}
}));

export default UserCard;
38 changes: 38 additions & 0 deletions components/generic/Loader.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { fr } from '@codegouvfr/react-dsfr';
import { makeStyles } from '@codegouvfr/react-dsfr/tss';

type Props = {
loadingMessage?: string;
};

export const Loader = (props: Props) => {
const { loadingMessage } = props;
const { classes, cx } = useStyles();

return (
<div className={cx(classes.loader)}>
<div>
<i className={fr.cx('ri-loader-4-line')} />
</div>
<p className={fr.cx('fr-pt-4v')}>{loadingMessage || 'Chargement...'}</p>
</div>
);
};

const useStyles = makeStyles()(theme => ({
loader: {
padding: fr.spacing('30v'),
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center',
i: {
display: 'inline-block',
animation: 'spin 1s linear infinite;',
color: theme.decisions.background.actionHigh.blueFrance.default,
['&::before']: {
'--icon-size': '2rem'
}
}
}
}));
Loading

0 comments on commit e68611b

Please sign in to comment.