Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Added complaint button, hidden as an easter egg 'complaint'. #791

Merged
merged 13 commits into from
Jun 18, 2024
Merged
24 changes: 24 additions & 0 deletions src/locale/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,30 @@
"coords": "coords",
"hide_document": "Hide geeks data",
"show_document": "Show geeks data",
"open_complaint": "Open complaint",
"close_complaint": "Close complaint",
"complaint": "Complaint",
"first_name": "First Name",
"last_name": "Last Name",
"id": "ID",
"email": "Email",
"phone": "Phone Number",
"complaint_type": "Complaint Type",
"other": "Other",
"no_stop": "No Stop at Station",
"no_ride": "No Ride",
"delay": "Delay",
"overcrowded": "Overcrowded",
"driver_behavior": "Driver Behavior",
"early": "Early Arrival",
"cleanliness": "Cleanliness and Condition of the Bus",
"fine_appeal": "Fine Appeal",
"route_change": "Route Change",
"line_switch": "Line Switch",
"station_signs": "Station Information Signs",
"description": "Description",
"submit_complaint": "Submit Complaint",

"lineProfile": {
"title": "Profile for Line",
"notFound": "We couldn't find the line you were looking for :(",
Expand Down
23 changes: 23 additions & 0 deletions src/locale/he.json
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,29 @@
"coords": "נ.צ.",
"hide_document": "הסתר מידע לגיקים",
"show_document": "הצג מידע לגיקים",
"open_complaint": "פתח תלונה",
"close_complaint": "סגור תלונה",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"close_complaint": "סגור תלונה",
"close_complaint": "בטל תלונה",

"complaint": "תלונה",
"first_name": "שם פרטי",
"last_name": "שם משפחה",
"id": "מספר תעודת זהות",
"email": "דואר אלקטרוני",
"phone": "מספר טלפון",
"complaint_type": "סוג התלונה",
"other": "אחר",
"no_stop": "אי עצירה בתחנה",
"no_ride": "אי ביצוע נסיעה",
"delay": "איחור",
"overcrowded": "עומס נוסעים",
"driver_behavior": "התנהגות נהג",
"early": "הקדמה",
"cleanliness": "נקיות ותקינות האוטובוס",
"fine_appeal": "ערעור על קנס",
"route_change": "שינוי מסלול",
"line_switch": "מעבר בין קווים",
"station_signs": "תקינות שלטי מידע בתחנה",
"description": "תיאור",
"submit_complaint": "שלח תלונה",
"lineProfile": {
"title": "פרופיל קו",
"notFound": "לא הצלחנו למצוא את הקו שחיפשת :(",
Expand Down
20 changes: 19 additions & 1 deletion src/pages/components/map-related/MapLayers/BusToolTip.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@ import { useTranslation } from 'react-i18next'
import CircularProgress from '@mui/material/CircularProgress'
import cn from 'classnames'
import CustomTreeView from '../../CustomTreeView'
import { EasterEgg } from '../../../EasterEgg/EasterEgg'
import ComplaintModal from './ComplaintModal'
import { getSiriRideWithRelated } from 'src/api/siriService'
import { Point } from 'src/pages/timeBasedMap'
import type { Point } from 'src/pages/timeBasedMap'

export type BusToolTipProps = { position: Point; icon: string; children?: ReactNode }

Expand All @@ -18,6 +20,7 @@ export function BusToolTip({ position, icon, children }: BusToolTipProps) {
const [isLoading, setIsLoading] = useState(false)
const [showJson, setShowJson] = useState(false)
const { t, i18n } = useTranslation()
const [modalOpen, setModalOpen] = useState(false)

useEffect(() => {
setIsLoading(true)
Expand Down Expand Up @@ -93,6 +96,21 @@ export function BusToolTip({ position, icon, children }: BusToolTipProps) {
onClick={() => setShowJson((showJson) => !showJson)}>
{showJson ? t('hide_document') : t('show_document')}
</Button>

{/* Open Complaint Button */}
<EasterEgg code="complaint">
<Button
variant="contained"
color="success"
onClick={() => setModalOpen((prev) => !prev)}
style={{ borderRadius: '50px' }}>
{t('open_complaint')}
</Button>
</EasterEgg>

{/* Complaint Modal */}
<ComplaintModal modalOpen={modalOpen} setModalOpen={setModalOpen} position={position} />

{showJson && (
<div onClick={(e) => e.stopPropagation()}>
<CustomTreeView<Point>
Expand Down
194 changes: 194 additions & 0 deletions src/pages/components/map-related/MapLayers/ComplaintModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
import { useState, ChangeEvent, useEffect } from 'react'
import {
Box,
Button,
FormControl,
InputLabel,
MenuItem,
Modal,
Select,
TextField,
SelectChangeEvent,
CircularProgress,
} from '@mui/material'
import { useTranslation } from 'react-i18next'
import { SiriRideWithRelatedPydanticModel } from 'open-bus-stride-client'
import { Point } from 'src/pages/timeBasedMap'
import { getSiriRideWithRelated } from 'src/api/siriService'

interface ComplaintModalProps {
modalOpen: boolean
setModalOpen: (open: boolean) => void
position: Point
}

const ComplaintModal = ({ modalOpen, setModalOpen, position }: ComplaintModalProps) => {
const { t, i18n } = useTranslation()
const [siriRide, setSiriRide] = useState<SiriRideWithRelatedPydanticModel | undefined>()
const [isLoading, setIsLoading] = useState(false)
const [complaintData, setComplaintData] = useState({
firstName: '',
lastName: '',
id: '',
email: '',
phone: '',
complaintType: '',
description: '',
})

useEffect(() => {
setIsLoading(true)
getSiriRideWithRelated(
position.point!.siri_route__id.toString(),
position.point!.siri_ride__vehicle_ref.toString(),
position.point!.siri_route__line_ref.toString(),
)
.then((siriRideRes: SiriRideWithRelatedPydanticModel) => setSiriRide(siriRideRes))
.finally(() => setIsLoading(false))
}, [position])

const modalStyle = {
position: 'absolute' as const,
top: '50%',
left: '50%',
transform: 'translate(-50%, -50%)',
width: 400,
bgcolor: 'background.paper',
border: '2px solid #000',
boxShadow: 24,
p: 4,
textAlign: i18n.language === 'he' ? 'left' : 'right',
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

something feels weird about this condition, are you sure it works as intended?

} as const

const handleInputChange = (e: ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => {
const { name, value } = e.target
setComplaintData((prevData) => ({ ...prevData, [name]: value }))
}

const handleSelectChange = (e: SelectChangeEvent<string>) => {
const { name, value } = e.target
setComplaintData((prevData) => ({ ...prevData, [name]: value }) as const)
}
const handleSubmit = () => {
const complaintPayload = {
userData: complaintData,
databusData: {
operator: siriRide?.gtfsRideGtfsRouteId,
...position,
},
}
console.log(complaintPayload)
// Handle the form submission, e.g., send it to an API
setModalOpen(false)
}

return (
<div>
{isLoading || !siriRide ? (
<div className="loading">
<span>{t('loading_routes')}</span>
<CircularProgress />
</div>
) : (
<Modal
open={modalOpen}
onClose={() => setModalOpen(false)}
aria-labelledby="modal-modal-title"
aria-describedby="modal-modal-description">
<Box className="modal" sx={modalStyle}>
<h2>{t('complaint')}</h2>
<form>
<TextField
label={t('first_name')}
name="firstName"
value={complaintData.firstName}
onChange={handleInputChange}
fullWidth
margin="normal"
/>
<TextField
label={t('last_name')}
name="lastName"
value={complaintData.lastName}
onChange={handleInputChange}
fullWidth
margin="normal"
/>
<TextField
label={t('id')}
name="id"
value={complaintData.id}
onChange={handleInputChange}
fullWidth
margin="normal"
/>
<TextField
label={t('email')}
name="email"
value={complaintData.email}
onChange={handleInputChange}
fullWidth
margin="normal"
/>
Comment on lines +125 to +132
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if you'll add type=email, then it will show better keyboard on some devices and also be more accessible.
same can be done for numbers and phone numbers
(can be done in future PR)

<TextField
label={t('phone')}
name="phone"
value={complaintData.phone}
onChange={handleInputChange}
fullWidth
margin="normal"
/>
<FormControl fullWidth margin="normal">
<InputLabel>{t('complaint_type')}</InputLabel>
<Select
name="complaintType"
value={complaintData.complaintType}
onChange={handleSelectChange}
sx={{ textAlign: i18n.language === 'he' ? 'left' : 'right' }}>
<MenuItem value="other">{t('other')}</MenuItem>
<MenuItem value="no_stop">{t('no_stop')}</MenuItem>
<MenuItem value="no_ride">{t('no_ride')}</MenuItem>
<MenuItem value="delay">{t('delay')}</MenuItem>
<MenuItem value="overcrowded">{t('overcrowded')}</MenuItem>
<MenuItem value="driver_behavior">{t('driver_behavior')}</MenuItem>
<MenuItem value="early">{t('early')}</MenuItem>
<MenuItem value="cleanliness">{t('cleanliness')}</MenuItem>
<MenuItem value="fine_appeal">{t('fine_appeal')}</MenuItem>
<MenuItem value="route_change">{t('route_change')}</MenuItem>
<MenuItem value="line_switch">{t('line_switch')}</MenuItem>
<MenuItem value="station_signs">{t('station_signs')}</MenuItem>
</Select>
</FormControl>
<TextField
label={t('description')}
name="description"
value={complaintData.description}
onChange={handleInputChange}
multiline
rows={4}
fullWidth
margin="normal"
/>
<Button
variant="contained"
color="primary"
onClick={handleSubmit}
style={{ marginTop: '16px', borderRadius: '50px' }}>
{t('submit_complaint')}
</Button>
</form>
<Button
variant="contained"
color="success"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this button will lead the user to cancel their complaint and potentially loose everything they typed

Suggested change
color="success"
color="danger"

onClick={() => setModalOpen(false)}
style={{ marginTop: '16px', borderRadius: '50px' }}>
{t('close_complaint')}
</Button>
</Box>
</Modal>
)}
</div>
)
}

export default ComplaintModal
Loading