-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #402 from COS301-SE-2024/fix/web/general-polishing-up
Fix/web/general polishing up
- Loading branch information
Showing
19 changed files
with
817 additions
and
304 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
const Employee = () => { | ||
return ( | ||
<svg | ||
width="24" | ||
height="24" | ||
viewBox="0 0 24 24" | ||
fill="none" | ||
xmlns="http://www.w3.org/2000/svg" | ||
> | ||
<g id="user-profile-square"> | ||
<path | ||
id="Icon" | ||
d="M4.1999 19.8003C4.54426 19.4146 6.85775 17.5977 8.00766 16.702C8.42646 16.3757 8.94017 16.2003 9.47104 16.2003C10.7547 16.2003 13.2283 16.2003 14.5181 16.2003C15.0552 16.2003 15.574 16.3832 16.0065 16.7017C17.4912 17.7956 18.8832 18.6106 20.3999 19.8003M5.9999 21.6H17.9999C19.9881 21.6 21.5999 19.9882 21.5999 18V6.00002C21.5999 4.0118 19.9881 2.40002 17.9999 2.40002H5.9999C4.01168 2.40002 2.3999 4.0118 2.3999 6.00002V18C2.3999 19.9882 4.01168 21.6 5.9999 21.6ZM15.4385 9.27206C15.4385 7.44055 13.8923 5.94411 11.9999 5.94411C10.1075 5.94411 8.56135 7.44055 8.56135 9.27206C8.56135 11.1036 10.1075 12.6 11.9999 12.6C13.8923 12.6 15.4385 11.1036 15.4385 9.27206Z" | ||
stroke="var(--primary-alt)" | ||
stroke-width="2" | ||
/> | ||
</g> | ||
</svg> | ||
); | ||
}; | ||
|
||
export default Employee; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,18 @@ | ||
const UserProfileGroup = () => { | ||
return ( | ||
<svg width="24" height="24" viewBox="0 0 24 24" fill="" xmlns="http://www.w3.org/2000/svg"> | ||
<path d="M18.088 16.8638C17.5434 16.9553 17.176 17.471 17.2675 18.0157C17.359 18.5603 17.8747 18.9277 18.4194 18.8362L18.088 16.8638ZM17.0152 11.3824C16.4629 11.3824 16.0152 11.8301 16.0152 12.3824C16.0152 12.9347 16.4629 13.3824 17.0152 13.3824V11.3824ZM16.0924 10.2827C17.5684 10.2827 18.7646 9.0858 18.7646 7.60999H16.7646C16.7646 7.98176 16.4633 8.28265 16.0924 8.28265V10.2827ZM13.4202 7.60999C13.4202 9.0858 14.6163 10.2827 16.0924 10.2827V8.28265C15.7214 8.28265 15.4202 7.98176 15.4202 7.60999H13.4202ZM16.0924 4.93734C14.6163 4.93734 13.4202 6.13419 13.4202 7.60999H15.4202C15.4202 7.23823 15.7214 6.93734 16.0924 6.93734V4.93734ZM18.7646 7.60999C18.7646 6.13419 17.5684 4.93734 16.0924 4.93734V6.93734C16.4633 6.93734 16.7646 7.23823 16.7646 7.60999H18.7646ZM20 15.1641C20 15.5763 19.8701 15.9126 19.6161 16.1792C19.3531 16.4551 18.8849 16.73 18.088 16.8638L18.4194 18.8362C19.524 18.6506 20.429 18.225 21.0638 17.5591C21.7075 16.8838 22 16.0369 22 15.1641H20ZM17.0152 13.3824C17.9362 13.3824 18.7269 13.6446 19.2605 14.0171C19.7974 14.3919 20 14.8131 20 15.1641H22C22 13.9788 21.3105 13.0091 20.4053 12.3771C19.4967 11.7429 18.295 11.3824 17.0152 11.3824V13.3824ZM10.2625 7.42936C10.2625 8.46511 9.58382 9.03069 8.89183 9.03069V11.0307C10.8184 11.0307 12.2625 9.43497 12.2625 7.42936H10.2625ZM8.89183 9.03069C8.19984 9.03069 7.52113 8.46511 7.52113 7.42936H5.52113C5.52113 9.43497 6.96521 11.0307 8.89183 11.0307V9.03069ZM7.52113 7.42936C7.52113 6.91225 7.69567 6.57237 7.9127 6.36129C8.1359 6.14421 8.4696 6 8.89183 6V4C8.00476 4 7.15311 4.31013 6.51827 4.92756C5.87728 5.55099 5.52113 6.42578 5.52113 7.42936H7.52113ZM8.89183 6C9.31406 6 9.64776 6.14421 9.87096 6.36129C10.088 6.57237 10.2625 6.91225 10.2625 7.42936H12.2625C12.2625 6.42578 11.9064 5.55099 11.2654 4.92756C10.6306 4.31013 9.7789 4 8.89183 4V6ZM14.0703 16.1679C14.0703 16.4806 13.9159 16.8937 13.1677 17.2838C12.3865 17.6911 11.0606 18 9.03513 18L9.03513 20C11.216 20 12.9076 19.6749 14.0924 19.0572C15.3103 18.4222 16.0703 17.4193 16.0703 16.1679H14.0703ZM9.03513 18C7.00965 18 5.68372 17.6911 4.90252 17.2838C4.1544 16.8937 4 16.4806 4 16.1679H2C2 17.4193 2.76001 18.4222 3.97789 19.0572C5.16268 19.6749 6.85432 20 9.03513 20L9.03513 18ZM4 16.1679C4 16.0022 4.18138 15.545 5.19247 15.0705C6.12422 14.6333 7.48172 14.3357 9.03513 14.3357V12.3357C7.25544 12.3357 5.59537 12.6722 4.34283 13.26C3.16963 13.8105 2 14.7695 2 16.1679H4ZM9.03513 14.3357C10.5886 14.3357 11.9461 14.6333 12.8778 15.0705C13.8889 15.545 14.0703 16.0022 14.0703 16.1679H16.0703C16.0703 14.7695 14.9006 13.8105 13.7274 13.26C12.4749 12.6722 10.8148 12.3357 9.03513 12.3357V14.3357Z" fill="var(--primary-alt)"/> | ||
</svg> | ||
) | ||
} | ||
return ( | ||
<svg | ||
width="24" | ||
height="24" | ||
viewBox="0 0 24 24" | ||
fill="" | ||
xmlns="http://www.w3.org/2000/svg" | ||
> | ||
<path | ||
d="M18.088 16.8638C17.5434 16.9553 17.176 17.471 17.2675 18.0157C17.359 18.5603 17.8747 18.9277 18.4194 18.8362L18.088 16.8638ZM17.0152 11.3824C16.4629 11.3824 16.0152 11.8301 16.0152 12.3824C16.0152 12.9347 16.4629 13.3824 17.0152 13.3824V11.3824ZM16.0924 10.2827C17.5684 10.2827 18.7646 9.0858 18.7646 7.60999H16.7646C16.7646 7.98176 16.4633 8.28265 16.0924 8.28265V10.2827ZM13.4202 7.60999C13.4202 9.0858 14.6163 10.2827 16.0924 10.2827V8.28265C15.7214 8.28265 15.4202 7.98176 15.4202 7.60999H13.4202ZM16.0924 4.93734C14.6163 4.93734 13.4202 6.13419 13.4202 7.60999H15.4202C15.4202 7.23823 15.7214 6.93734 16.0924 6.93734V4.93734ZM18.7646 7.60999C18.7646 6.13419 17.5684 4.93734 16.0924 4.93734V6.93734C16.4633 6.93734 16.7646 7.23823 16.7646 7.60999H18.7646ZM20 15.1641C20 15.5763 19.8701 15.9126 19.6161 16.1792C19.3531 16.4551 18.8849 16.73 18.088 16.8638L18.4194 18.8362C19.524 18.6506 20.429 18.225 21.0638 17.5591C21.7075 16.8838 22 16.0369 22 15.1641H20ZM17.0152 13.3824C17.9362 13.3824 18.7269 13.6446 19.2605 14.0171C19.7974 14.3919 20 14.8131 20 15.1641H22C22 13.9788 21.3105 13.0091 20.4053 12.3771C19.4967 11.7429 18.295 11.3824 17.0152 11.3824V13.3824ZM10.2625 7.42936C10.2625 8.46511 9.58382 9.03069 8.89183 9.03069V11.0307C10.8184 11.0307 12.2625 9.43497 12.2625 7.42936H10.2625ZM8.89183 9.03069C8.19984 9.03069 7.52113 8.46511 7.52113 7.42936H5.52113C5.52113 9.43497 6.96521 11.0307 8.89183 11.0307V9.03069ZM7.52113 7.42936C7.52113 6.91225 7.69567 6.57237 7.9127 6.36129C8.1359 6.14421 8.4696 6 8.89183 6V4C8.00476 4 7.15311 4.31013 6.51827 4.92756C5.87728 5.55099 5.52113 6.42578 5.52113 7.42936H7.52113ZM8.89183 6C9.31406 6 9.64776 6.14421 9.87096 6.36129C10.088 6.57237 10.2625 6.91225 10.2625 7.42936H12.2625C12.2625 6.42578 11.9064 5.55099 11.2654 4.92756C10.6306 4.31013 9.7789 4 8.89183 4V6ZM14.0703 16.1679C14.0703 16.4806 13.9159 16.8937 13.1677 17.2838C12.3865 17.6911 11.0606 18 9.03513 18L9.03513 20C11.216 20 12.9076 19.6749 14.0924 19.0572C15.3103 18.4222 16.0703 17.4193 16.0703 16.1679H14.0703ZM9.03513 18C7.00965 18 5.68372 17.6911 4.90252 17.2838C4.1544 16.8937 4 16.4806 4 16.1679H2C2 17.4193 2.76001 18.4222 3.97789 19.0572C5.16268 19.6749 6.85432 20 9.03513 20L9.03513 18ZM4 16.1679C4 16.0022 4.18138 15.545 5.19247 15.0705C6.12422 14.6333 7.48172 14.3357 9.03513 14.3357V12.3357C7.25544 12.3357 5.59537 12.6722 4.34283 13.26C3.16963 13.8105 2 14.7695 2 16.1679H4ZM9.03513 14.3357C10.5886 14.3357 11.9461 14.6333 12.8778 15.0705C13.8889 15.545 14.0703 16.0022 14.0703 16.1679H16.0703C16.0703 14.7695 14.9006 13.8105 13.7274 13.26C12.4749 12.6722 10.8148 12.3357 9.03513 12.3357V14.3357Z" | ||
fill="var(--primary-alt)" | ||
/> | ||
</svg> | ||
); | ||
}; | ||
|
||
export default UserProfileGroup | ||
export default UserProfileGroup; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
39 changes: 39 additions & 0 deletions
39
frontend/occupi-web/src/components/bookingsDashboardComponent/BookingsDashboard.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
import { useState } from "react"; | ||
import { Tabs, Tab } from "@nextui-org/react"; | ||
|
||
import { | ||
HistoricalBookingsBento, | ||
CurrentBookingsBento, | ||
TopBookingsBento, | ||
} from "@components/index"; | ||
|
||
const BookingsDashboard = () => { | ||
const [selected, setSelected] = useState("top"); | ||
|
||
return ( | ||
<div className="flex flex-col w-auto ml-3"> | ||
|
||
|
||
<Tabs | ||
className="mt-5 bg-text_col_alt" | ||
aria-label="Bookings tabs" | ||
selectedKey={selected} | ||
onSelectionChange={(key) => setSelected(key as string)} | ||
|
||
> | ||
<Tab key="top" title="Top Bookings"> | ||
<TopBookingsBento /> | ||
</Tab> | ||
<Tab key="current" title="Current Bookings"> | ||
<CurrentBookingsBento /> | ||
</Tab> | ||
<Tab key="historical" title="Historical Bookings"> | ||
<HistoricalBookingsBento /> | ||
</Tab> | ||
|
||
</Tabs> | ||
</div> | ||
); | ||
}; | ||
|
||
export default BookingsDashboard; |
174 changes: 174 additions & 0 deletions
174
frontend/occupi-web/src/components/currentBookings/CurrentBookingsBento.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,174 @@ | ||
import { useState, useEffect } from 'react'; | ||
import { Card, CardBody, CardHeader, Input, Button, Popover, PopoverTrigger, PopoverContent, Spinner } from "@nextui-org/react"; | ||
import { Calendar, Clock, Users, Search, ChevronDown } from 'lucide-react'; | ||
|
||
interface Booking { | ||
checkedIn: boolean; | ||
creators: string; | ||
date: string; | ||
emails: string[]; | ||
end: string; | ||
floorNo: string; | ||
occupiID: string; | ||
roomId: string; | ||
roomName: string; | ||
start: string; | ||
} | ||
|
||
interface ApiResponse { | ||
data: Booking[] | null; | ||
message: string; | ||
meta: { | ||
currentPage: number; | ||
totalPages: number; | ||
totalResults: number; | ||
}; | ||
status: number; | ||
} | ||
|
||
const CurrentBookingsBento = () => { | ||
const [bookings, setBookings] = useState<Booking[]>([]); | ||
const [filteredBookings, setFilteredBookings] = useState<Booking[]>([]); | ||
const [isLoading, setIsLoading] = useState(true); | ||
const [error, setError] = useState<string | null>(null); | ||
const [searchRoom, setSearchRoom] = useState(''); | ||
|
||
useEffect(() => { | ||
const fetchData = async () => { | ||
try { | ||
const response = await fetch('/analytics/bookings-current'); | ||
const data: ApiResponse = await response.json(); | ||
if (data.data) { | ||
setBookings(data.data); | ||
setFilteredBookings(data.data); | ||
} else { | ||
setBookings([]); | ||
setFilteredBookings([]); | ||
} | ||
setIsLoading(false); | ||
} catch (err) { | ||
setError('Failed to fetch data'); | ||
setIsLoading(false); | ||
} | ||
}; | ||
|
||
fetchData(); | ||
}, []); | ||
|
||
useEffect(() => { | ||
if (searchRoom) { | ||
const filtered = bookings.filter(booking => | ||
booking.roomName.toLowerCase().includes(searchRoom.toLowerCase()) | ||
); | ||
setFilteredBookings(filtered); | ||
} else { | ||
setFilteredBookings(bookings); | ||
} | ||
}, [searchRoom, bookings]); | ||
|
||
const formatTime = (timeString: string) => { | ||
return new Date(timeString).toLocaleTimeString('en-US', { | ||
hour: '2-digit', | ||
minute: '2-digit' | ||
}); | ||
}; | ||
|
||
if (isLoading) return <Spinner label="Loading..." />; | ||
if (error) return <div>Error: {error}</div>; | ||
|
||
return ( | ||
<div className="space-y-4 mt-5"> | ||
<Input | ||
type="text" | ||
placeholder="Search by room name" | ||
value={searchRoom} | ||
onChange={(e) => setSearchRoom(e.target.value)} | ||
startContent={<Search className="text-default-400" />} | ||
/> | ||
{filteredBookings.length > 0 ? ( | ||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4"> | ||
{filteredBookings.slice(0, 3).map((booking) => ( | ||
<Card key={booking.occupiID} className="w-full" shadow="sm"> | ||
<CardHeader className="flex justify-between"> | ||
<h4 className="text-large font-bold">{booking.roomName}</h4> | ||
<span className="text-small text-default-500">Floor {booking.floorNo}</span> | ||
</CardHeader> | ||
<CardBody> | ||
<div className="space-y-2"> | ||
<div className="flex items-center"> | ||
<Calendar className="mr-2 h-4 w-4" /> | ||
<span>{new Date(booking.date).toLocaleDateString()}</span> | ||
</div> | ||
<div className="flex items-center"> | ||
<Clock className="mr-2 h-4 w-4" /> | ||
<span>{formatTime(booking.start)} - {formatTime(booking.end)}</span> | ||
</div> | ||
<div className="flex items-center"> | ||
<Users className="mr-2 h-4 w-4" /> | ||
<span>{booking.emails.length} participant(s)</span> | ||
</div> | ||
<Popover placement="bottom"> | ||
<PopoverTrigger> | ||
<Button | ||
endContent={<ChevronDown className="h-4 w-4" />} | ||
variant="flat" | ||
> | ||
View Details | ||
</Button> | ||
</PopoverTrigger> | ||
<PopoverContent className="w-[300px]"> | ||
<div className="px-1 py-2"> | ||
<h3 className="text-small font-bold">Creator:</h3> | ||
<p className="text-tiny">{booking.creators}</p> | ||
<h3 className="text-small font-bold mt-2">Participants:</h3> | ||
<ul className="list-disc pl-4"> | ||
{booking.emails.map((email, i) => ( | ||
<li key={i} className="text-tiny">{email}</li> | ||
))} | ||
</ul> | ||
<p className="text-tiny mt-2"> | ||
Checked In: {booking.checkedIn ? 'Yes' : 'No'} | ||
</p> | ||
</div> | ||
</PopoverContent> | ||
</Popover> | ||
</div> | ||
</CardBody> | ||
</Card> | ||
))} | ||
</div> | ||
) : ( | ||
<Card> | ||
<CardBody> | ||
<p>No current bookings available.</p> | ||
</CardBody> | ||
</Card> | ||
)} | ||
{filteredBookings.length > 3 && ( | ||
<Popover placement="bottom"> | ||
<PopoverTrigger> | ||
<Button | ||
endContent={<ChevronDown className="h-4 w-4" />} | ||
variant="flat" | ||
> | ||
View More Bookings | ||
</Button> | ||
</PopoverTrigger> | ||
<PopoverContent className="w-[300px]"> | ||
<div className="px-1 py-2 max-h-[400px] overflow-y-auto"> | ||
{filteredBookings.slice(3).map((booking) => ( | ||
<div key={booking.occupiID} className="mb-4"> | ||
<h3 className="text-small font-bold">{booking.roomName}</h3> | ||
<p className="text-tiny">{new Date(booking.date).toLocaleDateString()}</p> | ||
<p className="text-tiny">{formatTime(booking.start)} - {formatTime(booking.end)}</p> | ||
</div> | ||
))} | ||
</div> | ||
</PopoverContent> | ||
</Popover> | ||
)} | ||
</div> | ||
); | ||
}; | ||
|
||
export default CurrentBookingsBento; |
Oops, something went wrong.