Skip to content

Commit

Permalink
comment deletion functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
rtrembecky committed Nov 10, 2023
1 parent d692f27 commit 13e6db1
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 55 deletions.
8 changes: 4 additions & 4 deletions src/components/Clickable/Clickable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,20 @@ import {ButtonHTMLAttributes, FC, ReactNode} from 'react'

import styles from './Clickable.module.scss'

interface ButtonProps {
type ButtonProps = {
onClick?: () => void
disabled?: boolean
children: ReactNode
type?: ButtonHTMLAttributes<HTMLButtonElement>['type']
}
} & Pick<ButtonHTMLAttributes<HTMLButtonElement>, 'type' | 'autoFocus'>

export const Button: FC<ButtonProps> = ({children, onClick, disabled, type}) => {
export const Button: FC<ButtonProps> = ({children, onClick, disabled, type, autoFocus}) => {
return (
<button
onClick={onClick}
className={clsx(styles.actionButton, disabled && styles.disabled)}
disabled={disabled}
type={type}
autoFocus={autoFocus}
>
{children}
</button>
Expand Down
131 changes: 80 additions & 51 deletions src/components/Problems/Discussion.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@ import clsx from 'clsx'
import {FC, useState} from 'react'

import {Comment, CommentState} from '@/types/api/competition'
import {Profile} from '@/types/api/personal'
import {AuthContainer} from '@/utils/AuthContainer'
import {useHasPermissions} from '@/utils/useHasPermissions'

import {Button} from '../Clickable/Clickable'
import {Dialog} from '../Dialog/Dialog'
import {Loading} from '../Loading/Loading'
import styles from './Discussion.module.scss'
import {SideContainer} from './SideContainer'
Expand All @@ -22,24 +24,25 @@ export const Discussion: FC<DiscussionProps> = ({problemId, problemNumber, close
const [commentText, setCommentText] = useState('')
const [hiddenResponseText, setHiddenResponseText] = useState('')
const [hiddenResponseDialogId, sethiddenResponseDialogId] = useState(-1)
const [deleteDialogId, setDeleteDialogId] = useState<number | undefined>()

const {data: commentsData, isLoading: commentsIsLoading} = useQuery({
queryKey: ['competition', 'problem', problemId, 'comments'],
queryFn: () => axios.get<Comment[]>(`/api/competition/problem/${problemId}/comments`),
})
const comments = commentsData?.data.map((comment) => ({
id: comment.id,
can_edit: comment.edit_allowed,
text: comment.text,
state: comment.state,
hidden_response: comment.hidden_response,
posted_by: comment.posted_by_name,
}))
const comments = commentsData?.data

const {hasPermissions} = useHasPermissions()

const {isAuthed} = AuthContainer.useContainer()

const {data} = useQuery({
queryKey: ['personal', 'profiles', 'myprofile'],
queryFn: () => axios.get<Profile>(`/api/personal/profiles/myprofile`),
enabled: isAuthed,
})
const userId = data?.data.id

const queryClient = useQueryClient()

const {mutate: addComment} = useMutation({
Expand Down Expand Up @@ -67,7 +70,7 @@ export const Discussion: FC<DiscussionProps> = ({problemId, problemNumber, close
},
})

const {mutate: deleteComment} = useMutation({
const {mutate: confirmDeleteComment} = useMutation({
mutationFn: (id: number) => axios.delete(`/api/competition/comment/${id}`),
onSuccess: () => {
queryClient.invalidateQueries({queryKey: ['competition', 'problem', problemId, 'comments']})
Expand All @@ -81,57 +84,83 @@ export const Discussion: FC<DiscussionProps> = ({problemId, problemNumber, close
setHiddenResponseText(e.currentTarget.value)
}

const close = () => setDeleteDialogId(undefined)
const agree = () => {
deleteDialogId !== undefined ? confirmDeleteComment(deleteDialogId) : undefined
close()
}

return (
<SideContainer title={'Diskusia - úloha ' + problemNumber} onClose={closeDiscussion}>
{/* delete comment dialog */}
<Dialog
open={deleteDialogId !== undefined}
close={close}
title="Vymazať komentár?"
contentText="Komentár bude nenávratne vymazaný."
actions={
<>
<Button onClick={close}>Zavrieť</Button>
<Button onClick={agree} autoFocus>
Potvrdiť
</Button>
</>
}
/>
<div className={styles.container}>
<div className={styles.comments}>
{commentsIsLoading && <Loading />}
{comments &&
comments.map((comment) => (
<div
className={clsx(styles.comment, comment.state !== CommentState.Published && styles.notPublished)}
key={comment.id}
>
<div className={styles.title}>
<div>{comment.posted_by}</div>
</div>
<div>{comment.text}</div>
{comment.hidden_response && (
<>
<div className={styles.title}>
<div>Vedúci:</div>
comments.map((comment) => {
const isPostedByMe = userId === comment.posted_by

return (
<div
className={clsx(styles.comment, comment.state !== CommentState.Published && styles.notPublished)}
key={comment.id}
>
<div className={styles.title}>
<div>{comment.posted_by_name}</div>
</div>
<div>{comment.text}</div>
{comment.hidden_response && (
<>
<div className={styles.title}>
<div>Vedúci:</div>
</div>
<div>{comment.hidden_response}</div>
</>
)}
{comment.state === CommentState.WaitingForReview && <div>* komentár čaká na schválenie</div>}
{comment.state === CommentState.Hidden && <div>* tento komentár nie je verejný</div>}
{hiddenResponseDialogId === comment.id ? (
<div className={styles.inputContainer}>
<textarea
className={styles.textArea}
value={hiddenResponseText}
onChange={handleHiddenResponseChange}
/>
<div className={styles.commentActions}>
<Button onClick={() => hideComment({id: comment.id, hiddenResponseText})}>Odoslať</Button>
</div>
</div>
<div>{comment.hidden_response}</div>
</>
)}
{comment.state === CommentState.WaitingForReview && <div>* komentár čaká na schválenie</div>}
{comment.state === CommentState.Hidden && <div>* tento komentár nie je verejný</div>}
{hiddenResponseDialogId === comment.id ? (
<div className={styles.inputContainer}>
<textarea
className={styles.textArea}
value={hiddenResponseText}
onChange={handleHiddenResponseChange}
/>
) : (
<div className={styles.commentActions}>
<Button onClick={() => hideComment({id: comment.id, hiddenResponseText})}>Odoslať</Button>
{comment.state !== CommentState.Published && hasPermissions && (
<Button onClick={() => publishComment(comment.id)}>Zverejniť</Button>
)}
{comment.state !== CommentState.Hidden && hasPermissions && (
<Button onClick={() => sethiddenResponseDialogId(comment.id)}>Skryť</Button>
)}
{/* veduci moze zmazat svoj komentar v hocijakom stave, ucastnik moze zmazat svoj nepublishnuty komentar */}
{isPostedByMe && (hasPermissions || comment.state !== CommentState.Published) && (
<Button onClick={() => setDeleteDialogId(comment.id)}>Vymazať</Button>
)}
</div>
</div>
) : (
<div className={styles.commentActions}>
{comment.state !== CommentState.Published && hasPermissions && (
<Button onClick={() => publishComment(comment.id)}>Zverejniť</Button>
)}
{comment.state !== CommentState.Hidden && hasPermissions && (
<Button onClick={() => sethiddenResponseDialogId(comment.id)}>Skryť</Button>
)}
{comment.state === CommentState.WaitingForReview && !hasPermissions && (
<Button onClick={() => deleteComment(comment.id)}>Vymazať</Button>
)}
</div>
)}
</div>
))}
)}
</div>
)
})}
</div>
<div className={styles.submitInputContainer}>
<textarea className={styles.textArea} value={commentText} onChange={handleCommentChange} />
Expand Down
1 change: 1 addition & 0 deletions src/types/api/personal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ export interface SchoolProfile {
}

export interface Profile {
id: number
first_name: string
last_name: string
nickname: string | null
Expand Down

0 comments on commit 13e6db1

Please sign in to comment.