Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/constants/translations/en/cooperations-page.json
Original file line number Diff line number Diff line change
Expand Up @@ -74,10 +74,10 @@
},
"notes": {
"noteText": "Note text...",
"privateSetting": "Make it private",
"noteMsg": "Note was successfully created"
"privateSetting": "Make it private"
},
"modalMessages": {
"successCreation": "Note was successfully created",
"successDeletion": "Note was deleted successfully",
"successDuplication": "Note was successfully duplicated",
"successUpdating": "Note was successfully updated",
Expand Down
4 changes: 2 additions & 2 deletions src/constants/translations/uk/cooperations-page.json
Original file line number Diff line number Diff line change
Expand Up @@ -75,10 +75,10 @@
},
"notes": {
"noteText": "Текст нотатки...",
"privateSetting": "Зробити приватною",
"noteMsg": "Нотатку було успішно створено"
"privateSetting": "Зробити приватною"
},
"modalMessages": {
"successCreation": "Нотатку було успішно створено",
"successDeletion": "Нотатку успішно видалено",
"successDuplication": "Нотатку було успішно продубльовано",
"successUpdating": "Нотатку було успішно оновлено",
Expand Down
255 changes: 103 additions & 152 deletions src/containers/my-cooperations/cooperation-notes/CooperationNotes.tsx
Original file line number Diff line number Diff line change
@@ -1,224 +1,175 @@
import { useState, useCallback } from 'react'
import { useState, useCallback, useEffect } from 'react'
import { useParams } from 'react-router-dom'
import { useTranslation } from 'react-i18next'
import Box from '@mui/material/Box'
import Divider from '@mui/material/Divider'
import Typography from '@mui/material/Typography'
import AddIcon from '@mui/icons-material/Add'

import useAxios from '~/hooks/use-axios'
import useConfirm from '~/hooks/use-confirm'
import { CooperationNotesService } from '~/services/cooperation-service'
import CreateOrEditNote from '~/containers/my-cooperations/cooperation-notes/create-or-edit-note/CreateOrEditNote'
import NoteView from '~/containers/my-cooperations/cooperation-notes/note-view/NoteView'
import Loader from '~/components/loader/Loader'
import { noteNotFoundError } from '~/containers/my-cooperations/cooperation-notes/CooperationNotes.constants'

import { snackbarVariants, defaultResponses } from '~/constants'
import { snackbarVariants } from '~/constants'
import { styles } from '~/containers/my-cooperations/cooperation-notes/CooperationNotes.styles'
import {
CreateOrUpdateNoteParams,
type CreateOrUpdateNoteParams,
PositionEnum,
ErrorResponse,
NoteResponse
type NoteResponse
} from '~/types'
import { useAppDispatch } from '~/hooks/use-redux'
import { openAlert } from '~/redux/features/snackbarSlice'
import { getErrorMessage } from '~/utils/error-with-message'
import { getErrorKey } from '~/utils/get-error-key'
import useSnackbarAlert from '~/hooks/use-snackbar-alert'
import useQuery from '~/hooks/use-query'
import useMutation from '~/hooks/use-mutation'
import { noteActionMap, NoteAction } from './constant'

const CooperationNotes = () => {
const CooperationNotes: React.FC = () => {
const { t } = useTranslation()
const { id = '' } = useParams()
const dispatch = useAppDispatch()
const { id: cooperationId = '' } = useParams()
const { openDialog } = useConfirm()
const [open, setOpen] = useState<boolean>(false)
const [editableItemId, setEditableItemId] = useState<string>('')
const { handleAlert, handleErrorAlert } = useSnackbarAlert()

const onResponseError = useCallback(
(error?: ErrorResponse) => {
const errorKey = getErrorKey(error)

dispatch(
openAlert({
severity: snackbarVariants.error,
message: error
? {
text: errorKey,
options: {
message: getErrorMessage(error.message)
}
}
: errorKey
})
)
},
[dispatch]
)

const onResponse = useCallback(() => {
dispatch(
openAlert({
severity: snackbarVariants.success,
message: 'cooperationsPage.notes.noteMsg'
})
)
}, [dispatch])
const onSuccessResponse = useCallback(
(noteAction: NoteAction) => {
const responseMessage = noteActionMap[noteAction]

const onDeleteResponse = useCallback(() => {
dispatch(
openAlert({
severity: snackbarVariants.success,
message: 'cooperationsPage.modalMessages.successDeletion'
})
)
}, [dispatch])
if (noteAction === 'create') {
setOpen(false)
}

const onUpdateResponse = useCallback(() => {
dispatch(
openAlert({
handleAlert({
severity: snackbarVariants.success,
message: 'cooperationsPage.modalMessages.successUpdating'
message: responseMessage
})
)
}, [dispatch])

const getNotes = useCallback(() => CooperationNotesService.getNotes(id), [id])

const createNoteService = useCallback(
(data: CreateOrUpdateNoteParams) =>
CooperationNotesService.createNote(id, data),
[id]
)

const deleteNote = useCallback(
(noteId?: string) =>
CooperationNotesService.deleteNote(id ?? '', noteId ?? ''),
[id]
},
[handleAlert]
)

const updateNoteService = useCallback(
(params: { noteId: string; data: CreateOrUpdateNoteParams }) =>
CooperationNotesService.updateNote(id, params.noteId, params.data),
[id]
)
const getNotes = useCallback(() => {
return CooperationNotesService.getNotes(cooperationId)
}, [cooperationId])

const {
response: notes,
loading,
fetchData
} = useAxios<NoteResponse[]>({
service: getNotes,
defaultResponse: defaultResponses.array,
onResponseError
data: notes,
isLoading: isNotesLoading,
error: getNotesError
} = useQuery({
queryKey: ['notes', cooperationId],
queryFn: getNotes,
options: {
staleTime: Infinity
}
})

const onNoteCreate = useCallback(() => {
onResponse()
setOpen(false)
void fetchData()
}, [onResponse, fetchData])

const { loading: createLoading, fetchData: addNewNote } = useAxios({
service: createNoteService,
defaultResponse: null,
fetchOnMount: false,
onResponseError,
onResponse: onNoteCreate
})
useEffect(() => {
if (getNotesError) {
handleErrorAlert(getNotesError)
}
}, [handleErrorAlert, getNotesError])

const { error, fetchData: deleteItem } = useAxios({
service: deleteNote,
fetchOnMount: false,
defaultResponse: null,
onResponseError,
onResponse: onDeleteResponse
})
const createNote = useCallback(
(data: CreateOrUpdateNoteParams) => {
return CooperationNotesService.createNote(cooperationId, data)
},
[cooperationId]
)

const {
error: updateError,
loading: updateLoading,
fetchData: updateNote
} = useAxios({
service: updateNoteService,
fetchOnMount: false,
defaultResponse: null,
onResponseError,
onResponse: onUpdateResponse
const { mutate: addNewNote, isPending: createLoading } = useMutation({
mutationFn: createNote,
queryKey: ['notes', cooperationId],
onError: handleErrorAlert,
onSuccess: () => onSuccessResponse('create')
})

const handleDelete = async (id: string, isConfirmed: boolean) => {
if (isConfirmed) {
await deleteItem(id)
if (!error) await fetchData()
}
}
const deleteSelectedNote = useCallback(
(noteId: string) => {
return CooperationNotesService.deleteNote(cooperationId, noteId)
},
[cooperationId]
)

const { mutate: deleteNote } = useMutation({
mutationFn: deleteSelectedNote,
queryKey: ['notes', cooperationId],
onError: handleErrorAlert,
onSuccess: () => onSuccessResponse('delete')
})

const onDeleteNote = (id: string) => {
openDialog({
message: 'cooperationsPage.modalMessages.confirmDeletionMessage',
sendConfirm: (isConfirmed: boolean) => void handleDelete(id, isConfirmed),
title: `cooperationsPage.modalMessages.confirmDeletionTitle`
title: `cooperationsPage.modalMessages.confirmDeletionTitle`,
sendConfirm: (isConfirmed: boolean) => {
if (isConfirmed) {
deleteNote(id)
}
}
})
}

const updateSelectedNote = useCallback(
(params: { noteId: string; data: CreateOrUpdateNoteParams }) => {
return CooperationNotesService.updateNote(
cooperationId,
params.noteId,
params.data
)
},
[cooperationId]
)

const { mutate: updateNote, isPending: updateNoteLoading } = useMutation({
mutationFn: updateSelectedNote,
queryKey: ['notes', cooperationId],
onError: handleErrorAlert,
onSuccess: () => onSuccessResponse('update')
})

const duplicateNote = useCallback(
(id: string) => {
const note = notes.find((item) => item._id === id)
(noteId: string) => {
const note = notes?.data.find((item) => item._id === noteId)

if (!note) {
return Promise.reject(noteNotFoundError)
throw new Error('Note with specified ID was not found')
}

return createNoteService(note)
return CooperationNotesService.createNote(cooperationId, note)
},
[notes, createNoteService]
[cooperationId, notes]
)

const onDuplicateResponse = () => {
dispatch(
openAlert({
severity: snackbarVariants.success,
message: `cooperationsPage.modalMessages.successDuplication`
})
)
}

const { error: duplicationError, fetchData: duplicateItem } = useAxios({
service: duplicateNote,
fetchOnMount: false,
defaultResponse: null,
onResponseError,
onResponse: onDuplicateResponse
const { mutate: duplicateItem } = useMutation({
mutationFn: duplicateNote,
queryKey: ['notes', cooperationId],
onSuccess: () => onSuccessResponse('duplicate'),
onError: handleErrorAlert
})

const handleDuplicate = async (itemId: string) => {
await duplicateItem(itemId)
if (!duplicationError) await fetchData()
}

const handleUpdate = async (data: CreateOrUpdateNoteParams) => {
await updateNote({ noteId: editableItemId, data })
const handleUpdate = (data: CreateOrUpdateNoteParams) => {
updateNote({ noteId: editableItemId, data })
onCloseEdit()
if (!updateError) await fetchData()
}

const onCloseEdit = () => setEditableItemId('')
const onCloseNote = () => setOpen(false)
const onAddNoteOpen = () => setOpen(true)

const NotesList = notes.map((item: NoteResponse) =>
const notesList = notes?.data.map((item: NoteResponse) =>
editableItemId === item._id ? (
<CreateOrEditNote
key={item._id}
note={item}
onCloseNote={onCloseEdit}
onSubmit={handleUpdate}
onSubmitLoading={updateLoading}
onSubmitLoading={updateNoteLoading}
/>
) : (
<NoteView
deleteItem={onDeleteNote}
duplicateItem={(itemId: string) => void handleDuplicate(itemId)}
duplicateItem={duplicateItem}
key={item._id}
note={item}
updateItem={setEditableItemId}
Expand All @@ -241,7 +192,7 @@ const CooperationNotes = () => {
onSubmitLoading={createLoading}
/>
)}
{loading ? <Loader pageLoad /> : NotesList}
{isNotesLoading || !notes ? <Loader pageLoad /> : notesList}
</Box>
</Box>
)
Expand Down
8 changes: 8 additions & 0 deletions src/containers/my-cooperations/cooperation-notes/constant.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export type NoteAction = 'create' | 'delete' | 'update' | 'duplicate'

export const noteActionMap: Record<NoteAction, string> = {
create: 'cooperationsPage.modalMessages.successCreation',
delete: 'cooperationsPage.modalMessages.successDeletion',
duplicate: 'cooperationsPage.modalMessages.successDuplication',
update: 'cooperationsPage.modalMessages.successUpdating'
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ import {
interface CreateOrEditNoteProps {
note?: NoteResponse
onSubmitLoading: boolean
onSubmit: (data: CreateOrUpdateNoteParams) => Promise<void>
onSubmit: (data: CreateOrUpdateNoteParams) => void
onCloseNote: () => void
}

Expand Down Expand Up @@ -65,8 +65,8 @@ const CreateOrEditNote = ({
text: note?.text ?? '',
isPrivate: note?.isPrivate ?? false
},
onSubmit: async () => {
await onSubmit(data)
onSubmit: () => {
onSubmit(data)
}
})

Expand Down
Loading