porridger/front/src/components/AnnouncementDetails.tsx

161 lines
4.7 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { Modal, Button } from 'react-bootstrap'
import { MapContainer, Marker, Popup, TileLayer } from 'react-leaflet'
import { CSSProperties, useState } from 'react'
import { LatLng } from 'leaflet'
import LineDot from './LineDot'
import { categoryNames } from '../assets/category'
import { useBook, useRemoveAnnouncement } from '../hooks/api'
import { Announcement } from '../api/announcement/types'
import { iconItem } from '../utils/markerIcons'
import { useId } from '../hooks'
import SelectDisposalTrashbox from './SelectDisposalTrashbox'
import StarRating from './StarRating'
const styles = {
container: {
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
} as CSSProperties,
map: {
width: '100%',
minHeight: 300,
} as CSSProperties,
}
type ViewProps = {
myId: number,
announcement: Announcement,
}
const View = ({
myId,
announcement: { name, category, bestBy, description, lat, lng, address, metro, userId },
}: ViewProps) => (
<>
<h1>{name}</h1>
<span>{categoryNames[category]}</span>
<span className='m-2'>&#x2022;</span>{/* dot */}
<span>Годен до {new Date(bestBy).toLocaleString('ru-RU')}</span>
<p className='mb-0'>{description}</p>
<p className='mb-3'>
Рейтинг пользователя: <StarRating dynamic={myId !== userId} userId={userId} />
</p>
<MapContainer style={styles.map} center={[lat, lng]} zoom={16} >
<TileLayer
attribution='&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
url='https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png'
/>
<Marker icon={iconItem} position={[lat, lng]}>
<Popup>
{address}
<br />
<LineDot station={metro} /> {metro}
</Popup>
</Marker>
</MapContainer>
</>
)
type ControlProps = {
myId: number,
closeRefresh: () => void,
announcement: Announcement,
showDispose: () => void
}
function Control({
myId,
closeRefresh,
announcement: { bookedBy, id, userId },
showDispose,
}: ControlProps) {
const { handleBook, bookButton } = useBook()
const { handleRemove, removeButton } = useRemoveAnnouncement(closeRefresh)
return (
<>
<p>Забронировали {bookedBy + (bookButton.disabled ? 1 : 0)} чел.</p>
{(myId === userId) ? (
<>
<Button variant='success' onClick={showDispose}>Утилизировать</Button>
<Button variant='success' onClick={() => void handleRemove(id)} {...removeButton} />
</>
) : (
<Button variant='success' onClick={() => void handleBook(id)} {...bookButton} />
)}
</>
)
}
type AnnouncementDetailsProps = {
close: () => void,
refresh: () => void,
announcement: Announcement,
}
function AnnouncementDetails({
close,
refresh,
announcement,
}: AnnouncementDetailsProps) {
const closeRefresh = () => {
close()
refresh()
}
const [disposeShow, setDisposeShow] = useState(false)
const myId = useId()
return (
<div
className='modal'
style={styles.container}
>
<Modal.Dialog centered className='modal-dialog'>
<Modal.Header closeButton onHide={close}>
<Modal.Title>
Подробнее
</Modal.Title>
</Modal.Header>
<Modal.Body>
<View myId={myId} announcement={announcement} />
</Modal.Body>
<Modal.Footer>
<Control
myId={myId}
closeRefresh={closeRefresh}
showDispose={() => setDisposeShow(true)}
announcement={announcement}
/>
</Modal.Footer>
</Modal.Dialog>
<Modal centered show={disposeShow} onHide={() => setDisposeShow(false)} style={{ zIndex: 100000 }}>
<Modal.Header closeButton>
<Modal.Title>
Утилизация
</Modal.Title>
</Modal.Header>
<SelectDisposalTrashbox
annId={announcement.id}
category={announcement.category}
address={new LatLng(announcement.lat, announcement.lng)}
closeRefresh={closeRefresh}
/>
</Modal>
</div>
)
}
export default AnnouncementDetails