2024-07-27 16:42:03 +02:00

161 lines
4.9 KiB
TypeScript

import { Person } from '@mui/icons-material';
import {
Alert,
Avatar,
Button,
Card,
CardActions,
CardContent,
CardHeader,
Dialog,
DialogActions,
DialogContent,
DialogContentText,
DialogTitle,
Link as MUILink,
Snackbar,
Typography,
} from '@mui/material';
import { useMutation, useQueryClient } from '@tanstack/react-query';
import { Link } from '@tanstack/react-router';
import { FC, useState } from 'react';
import { useTranslation } from 'react-i18next';
import Api from '../../api/Api';
import { PostAuth, PostNonAuth } from '../../types/Post';
import convertDate from '../../utils/date';
import PostEditDialog from '../Dialogs/PostEdit/PostEditDialog';
import ErrorComponent from '../Error/ErrorComponent';
interface Props {
post: PostNonAuth | PostAuth;
}
const Post: FC<Props> = ({ post }) => {
const [deleteOpen, setDeleteOpen] = useState(false);
const [editOpen, setEditOpen] = useState(false);
//eslint-disable-next-line @typescript-eslint/no-explicit-any
const [error, setError] = useState<any>();
const deleteMutation = useMutation({
mutationFn: (id: number) => {
return Api.deletePost(id);
},
});
const queryClient = useQueryClient();
const { t } = useTranslation();
return (
<Card>
<CardHeader
avatar={
'id' in post.user ? (
post.user.id !== Api.getAuthenticatedUser()?.id ? (
<MUILink component={Link} to="/profile/$id" params={{ id: post.user.id }}>
<Avatar alt={post.user.username} src={`storage/${post.user.image}`}>
<Person />
</Avatar>
</MUILink>
) : (
<MUILink component={Link} to="/profile">
<Avatar alt={post.user.username} src={`storage/${post.user.image}`}>
<Person />
</Avatar>
</MUILink>
)
) : (
<Avatar alt={post.user.username} src={`storage/${post.user.image}`}>
<Person />
</Avatar>
)
}
title={
'id' in post.user ? (
post.user.id !== Api.getAuthenticatedUser()?.id ? (
<MUILink component={Link} to="/profile/$id" params={{ id: post.user.id }}>
{post.user.username}
</MUILink>
) : (
<MUILink component={Link} to="/profile">
{post.user.username}
</MUILink>
)
) : (
post.user.username
)
}
subheader={convertDate(post.postedAt)}
/>
<CardContent>
<Typography>
<span dangerouslySetInnerHTML={{ __html: post.content }} />
</Typography>
</CardContent>
<CardActions>
{(Api.isAdmin() || ('id' in post.user && post.user.id === Api.getAuthenticatedUser()?.id)) && (
<>
<Button size="small" onClick={() => setEditOpen(true)}>
{t('Edit')}
</Button>
<PostEditDialog post={post as PostAuth} open={editOpen} onClose={() => setEditOpen(false)} />
</>
)}
{Api.isAdmin() && (
<>
<Button size="small" color="error" onClick={() => setDeleteOpen(true)}>
{t('Delete')}
</Button>
<Dialog open={deleteOpen} onClose={() => setDeleteOpen(false)}>
<DialogTitle>{t('Confirm post delete title')}</DialogTitle>
<DialogContent>
<DialogContentText>{t('Confirm post delete body', { name: post.user.username })}</DialogContentText>
</DialogContent>
<DialogActions>
<Button onClick={() => setDeleteOpen(false)} autoFocus variant="contained">
{t('No')}
</Button>
<Button
variant="outlined"
color="error"
onClick={() => {
deleteMutation.mutate(post.id, {
onSuccess: () => {
queryClient.invalidateQueries({
queryKey: ['posts'],
});
},
onError: setError,
});
setDeleteOpen(false);
}}
>
{t('Yes')}
</Button>
</DialogActions>
</Dialog>
</>
)}
</CardActions>
<Snackbar
open={deleteMutation.isError}
autoHideDuration={2000}
onClose={() => {
deleteMutation.reset();
}}
TransitionProps={{
onExited: () => setError(undefined),
}}
>
<Alert severity="error" variant="filled" sx={{ width: '100%' }}>
{error && <ErrorComponent error={error} context="delete" color="white" />}
</Alert>
</Snackbar>
<Snackbar open={deleteMutation.isPending} message={t('Deleting')} />
</Card>
);
};
export default Post;