Skip to content

Commit

Permalink
update
Browse files Browse the repository at this point in the history
  • Loading branch information
QuocAnh189 committed Dec 11, 2024
1 parent 095e3fe commit d2e2713
Show file tree
Hide file tree
Showing 61 changed files with 1,385 additions and 1,402 deletions.
4 changes: 4 additions & 0 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ const Customer = lazy(() => import('@pages/dashboard/Customer'))
const Payment = lazy(() => import('@pages/dashboard/Payment'))
const EventDetail = lazy(() => import('@pages/events/Event-Detail'))
const Profile = lazy(() => import('@pages/setting/Profile'))
const Follower = lazy(() => import('@pages/setting/Follower'))
const Following = lazy(() => import('@pages/setting/Following'))
const Explore = lazy(() => import('@pages/explore/Explore'))
const CreateEvent = lazy(() => import('@pages/events/Create-Event'))
const UpdateEvent = lazy(() => import('@pages/events/Update-Event'))
Expand Down Expand Up @@ -106,6 +108,8 @@ function App() {
<Route path='/organization/order' element={<Order />} />
<Route path='/organization/review' element={<Review />} />
<Route path='/organization/settings/profile' element={<Profile />} />
<Route path='/organization/settings/follower' element={<Follower />} />
<Route path='/organization/settings/following' element={<Following />} />
</Route>
<Route path='/*' element={<NotFound />} />
</Routes>
Expand Down
211 changes: 51 additions & 160 deletions src/components/Comments.tsx
Original file line number Diff line number Diff line change
@@ -1,140 +1,32 @@
// hook
import { useEffect, useState } from 'react'
import { usePagination } from '@hooks/index'

//component
import FormControl from '@mui/material/FormControl'
import Divider from '@mui/material/Divider'
import TextField from '@mui/material/TextField'
// //component
import ItemReview from './ItemReview'
import CircularProgress from '@mui/material/CircularProgress'
import Pagination from '@ui/Pagination'
import ConfirmDialog from './Dialog'
import { toast } from 'react-toastify'

//icons
import { MdStarRate } from 'react-icons/md'

//interface and type
import { IMetadataReviewResponse, initParamsReview, IReviewEventPayload } from '@type/event.type'
import { IReview } from 'interfaces/contents/review.interface'
import Pagination from '@ui/Pagination'

//redux
import { useAppSelector } from '@hooks/useRedux'
import { useGetReviewsByEventIdQuery, useAddReviewMutation, useDeleteReviewMutation } from '@redux/apis/event.api'
import { useGetReviewsByEventIdQuery } from '@redux/apis/review.api'
import { useAddReviewMutation } from '@redux/apis/event.api'

//util
import dayjs from 'dayjs'
import classNames from 'classnames'
import { IReview } from '@interfaces/contents'
import { usePagination } from '@hooks/usePagination'

//assets
import userDefault from '@assets/images/common/user_default.png'
// //data
// import reviews_data from '@db/reviews'

//data
import reviews_data from '@db/reviews'
//interface
import { IUser } from '@interfaces/systems'
import { IReviewEventPayload } from '@type/event.type'

interface Props {
eventId: string
ownerId: string
}

const ItemReviews = (props: Props) => {
const { eventId, ownerId } = props

const user = useAppSelector((state) => state.persistedReducer.user.user)

const [openDialog, setOpenDialog] = useState<boolean>(false)
const [reviewIdSelected, setReviewIdSelected] = useState<string>('')

const [metadata, setMetadata] = useState<IMetadataReviewResponse>()
const [reviews, setReviews] = useState<IReview[]>([])

const pagination = usePagination(metadata?.totalCount! || reviews_data.length, initParamsReview.size)

const { data } = useGetReviewsByEventIdQuery({ ...initParamsReview, eventId, page: pagination.currentPage || 1 })
const [deleteReview, { isLoading: loadingDeleteReview }] = useDeleteReviewMutation()

useEffect(() => {
if (data) {
setMetadata(data.metadata)
setReviews(data.items)
}
}, [data])

const handleDeleteReview = async (reviewId: string) => {
try {
const result = await deleteReview({ eventId, reviewId }).unwrap()
if (result) {
setOpenDialog(false)
}
} catch (e) {
console.log(e)
}
}

return (
<div className='space-y-2'>
{reviews_data.slice(0, 3).map((review: IReview, index: number) => (
<div key={`index${index}`} className='space-y-4'>
<div className='flex items-center justify-between gap-2'>
<div className='flex items-center gap-2'>
<img
src={review.userAvatar ? review.userAvatar : userDefault}
alt=''
className='w-[40px] h-[40px] object-cover rounded-full'
/>
<div className=''>
<div className='flex items-center gap-2'>
<p className='font-semibold text-header'>{review.fullName}</p>
{review.userId === ownerId && <p className='font-medium text-header'>(Author)</p>}
</div>
<div className='flex items-center'>
{[1, 2, 3, 4, 5].map((rate, index) => (
<MdStarRate key={`rate-${index}`} color={rate <= review.rate ? 'orange' : 'gray'} />
))}
</div>
</div>
</div>
<p className='text-sm text-gray500'>{dayjs(review.createdAt).format('DD/MM/YYYY hh:mm A').toString()}</p>
</div>
<div className='flex items-center gap-2'>
<p className='text-gray500'>{review.content}.</p>
{review.userId === user?.id && (
<button
onClick={() => {
setOpenDialog(true)
setReviewIdSelected(review.id!)
}}
className='font-medium text-header hover:underline text-textError'
>
Delete
</button>
)}
</div>
<Divider />
</div>
))}
{reviews.length === 0 && <p className='text-header text-center text-xl w-full'>No comments here</p>}
<div className='w-full relative'>
<div className='absolute right-0 translate-x-[50%]'>
{pagination.maxPage > 1 && <Pagination pagination={pagination} />}
</div>
</div>
{openDialog && (
<ConfirmDialog
title='Delete Comment'
description='Do you want to delete this message'
open={openDialog}
setOpen={(value: any) => {
setOpenDialog(value)
}}
action='Ok'
disabled={loadingDeleteReview}
onHandle={() => {
handleDeleteReview(reviewIdSelected)
}}
/>
)}
</div>
)
const initParams = {
page: 1,
pageSize: 5
}

interface Props {
Expand All @@ -144,9 +36,10 @@ interface Props {

const Comments = (props: Props) => {
const { eventId, ownerId } = props
const user: IUser = useAppSelector((state) => state.persistedReducer.user.user)

const user = useAppSelector((state) => state.persistedReducer.user.user)

const [params, setParams] = useState(initParams)
const { data } = useGetReviewsByEventIdQuery({ eventId, params })
const [addReview, { isLoading }] = useAddReviewMutation()

const [rate, setRate] = useState<number>(0.0)
Expand All @@ -168,13 +61,34 @@ const Comments = (props: Props) => {
}
}

const pagination = usePagination(data?.metadata.totalCount, data?.metadata.pageSize)

useEffect(() => {
setParams({ ...params, page: pagination.currentPage })
}, [pagination.currentPage])

return (
<div className='space-y-8 mdl:w-1/2 mdl:pl-[150px]'>
<div className='w-full space-y-4'>
<ItemReviews eventId={eventId} ownerId={ownerId} />
<div className='space-y-8 mdl:w-full mdl:pl-[150px]'>
<div className='w-1/2 space-y-4'>
<div className='space-y-2'>
<div className='w-full relative'>
{data?.items.map((review: IReview, index: number) => (
<ItemReview
key={`review-${review.id}`}
index={index}
review={review}
ownerId={ownerId}
userId={user.id!}
/>
))}
</div>
</div>
</div>
<div className='w-full flex items-center justify-center'>
{pagination && pagination.maxPage > 1 && <Pagination pagination={pagination} />}
</div>

<div className='w-full flex flex-col gap-2'>
<div className='w-1/2 flex flex-col gap-2'>
<div className='flex flex-row items-center gap-2 mt-10'>
<p className='text-header'>Rate</p>
<button className='flex items-center gap-1 label-text leading-none w-[30px] hover:cursor-pointer'>
Expand All @@ -187,36 +101,13 @@ const Comments = (props: Props) => {
))}
</button>
</div>
<FormControl>
<TextField
value={content}
onChange={(e) => {
setContent(e.target.value)
}}
sx={{
'& label': { color: 'var(--header)' },
'& .MuiOutlinedInput-input': {
color: 'var(--header)'
},
'& .MuiOutlinedInput-root': {
'& fieldset': {
borderColor: 'var(--header)'
},
'&:hover fieldset': {
borderColor: 'var(--header)'
},
'&.Mui-focused fieldset': {
borderColor: 'var(--header)'
}
}
}}
error={false}
multiline={true}
rows={2}
id='outlined-basic'
label='Comments here'
/>
</FormControl>
<textarea
className={classNames(`field-input !h-[120px] !py-[15px] !overflow-y-auto`)}
id='comment'
value={content}
placeholder='Comments here'
onChange={(e) => setContent(e.target.value)}
/>
<button disabled={isLoading} onClick={handleAddReviews} className='btn btn-primary hover:bg-primary-400 w-40'>
{isLoading ? <CircularProgress size={24} /> : 'Post comment'}
</button>
Expand Down
61 changes: 28 additions & 33 deletions src/components/FormToChat.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
//hooks
import { useContext } from 'react'

//components
import FormControl from '@mui/material/FormControl'

//context
import { AppSocketContext } from '@contexts/socket.context'

Expand Down Expand Up @@ -33,42 +30,40 @@ const FormToChat = (props: Props) => {
<br />
Do not hesitate to contact me.
</p>
<FormControl>
<div className='flex flex-col gap-3'>
<div className='flex items-center gap-4 text-header'>
<div className='field-wrapper'>
<label className='field-label' htmlFor='qty'>
Name
</label>
<input
readOnly
className={classNames('field-input')}
id='qty'
placeholder='Enter name'
value={userFullName}
/>
</div>
<div className='field-wrapper'>
<label className='field-label' htmlFor='qty'>
Email
</label>
<input
readOnly
className={classNames('field-input')}
id='qty'
placeholder='Enter email'
value={userEmail}
/>
</div>
<div className='flex flex-col gap-3'>
<div className='flex items-center gap-4 text-header'>
<div className='field-wrapper'>
<label className='field-label' htmlFor='qty'>
Name
</label>
<input
readOnly
className={classNames('field-input')}
id='qty'
placeholder='Enter name'
value={userFullName}
/>
</div>
<div className='field-wrapper'>
<label className='field-label' htmlFor='qty'>
Event
Email
</label>
<input readOnly className={classNames('field-input')} id='qty' value={eventName} />
<input
readOnly
className={classNames('field-input')}
id='qty'
placeholder='Enter email'
value={userEmail}
/>
</div>
</div>
</FormControl>
<div className='field-wrapper'>
<label className='field-label' htmlFor='qty'>
Event
</label>
<input readOnly className={classNames('field-input')} id='qty' value={eventName} />
</div>
</div>
<button
onClick={() => handleJoinChatRoom && handleJoinChatRoom({ eventId, hostId, userId })}
className='btn btn-primary w-40 hover:bg-primary-500'
Expand Down
Loading

0 comments on commit d2e2713

Please sign in to comment.