From c7789f3433a8351f59f83f3e7ddcca0f40fbea42 Mon Sep 17 00:00:00 2001 From: "riho.takagi" Date: Mon, 23 Oct 2023 16:10:16 -0400 Subject: [PATCH 1/4] separate tabs --- .../client/admin-page/components/Admin.tsx | 369 +---------------- .../client/admin-page/components/Bookings.tsx | 385 ++++++++++++++++++ 2 files changed, 388 insertions(+), 366 deletions(-) create mode 100644 media_commons_booking_app/src/client/admin-page/components/Bookings.tsx diff --git a/media_commons_booking_app/src/client/admin-page/components/Admin.tsx b/media_commons_booking_app/src/client/admin-page/components/Admin.tsx index 37900733..04dfb3f2 100644 --- a/media_commons_booking_app/src/client/admin-page/components/Admin.tsx +++ b/media_commons_booking_app/src/client/admin-page/components/Admin.tsx @@ -1,154 +1,16 @@ import React, { useState, useEffect } from 'react'; // This is a wrapper for google.script.run that lets us use promises. -import { serverFunctions } from '../../utils/serverFunctions'; -import { Inputs } from '../../booking/components/FormInput'; + import { SafetyTraining } from './SafetyTraining'; import { Ban } from './Ban'; import { AdminUsers } from './AdminUsers'; import { Liaisons } from './Liaisons'; -import { formatDate } from '../../utils/date'; - -const BOOKING_SHEET_NAME = 'bookings'; - -type Booking = Inputs & { - calendarEventId: string; - email: string; - startDate: string; - endDate: string; - roomId: string; -}; - -type BookingStatus = { - calendarEventId: string; - email: string; - requestedAt: string; - firstApprovedAt: string; - secondApprovedAt: string; - rejectedAt: string; - canceledAt: string; - checkedInAt: string; -}; +import { Bookings } from './Bookings'; const Admin = () => { - const [bookings, setBookings] = useState([]); - const [mappingBookings, setMappingBookings] = useState([]); - const [mappingBookingStatuses, setMappingBookingStatuses] = useState([]); - const [bookingStatuses, setBookingStatuses] = useState([]); - const [showModal, setShowModal] = useState(false); - const [selectedInfo, setSelectedInfo] = useState(); const [tab, setTab] = useState('bookings'); - useEffect(() => { - fetchBookings(); - fetchBookingStatuses(); - }, []); - useEffect(() => { - const mappings = bookings - .map((booking, index) => { - if (index !== 0) { - return mappingBookingRows(booking); - } - }) - .filter((booking) => booking !== undefined); - //TODO: filter out bookings that are not in the future - setMappingBookings(mappings); - }, [bookings]); - - useEffect(() => { - const mappings = bookingStatuses - .map((bookingStatus, index) => { - if (index !== 0) { - return mappingBookingStatusRow(bookingStatus); - } - }) - .filter((booking) => booking !== undefined); - console.log('mapping status', mappings); - setMappingBookingStatuses(mappings); - }, [bookingStatuses]); - - const fetchBookings = async () => { - serverFunctions.fetchRows(BOOKING_SHEET_NAME).then((rows) => { - console.log('booking rows', rows); - setBookings(rows); - }); - }; - - const fetchBookingStatuses = async () => { - serverFunctions.fetchRows('bookingStatus').then((statusRows) => { - console.log('bookingStatuses rows', statusRows); - setBookingStatuses(statusRows); - }); - }; - - const mappingBookingRows = (values: string[]): Booking => { - return { - calendarEventId: values[0], - roomId: values[1], - email: values[2], - startDate: values[3], - endDate: values[4], - firstName: values[5], - lastName: values[6], - secondaryName: values[7], - nNumber: values[8], - netId: values[9], - phoneNumber: values[10], - department: values[11], - role: values[12], - sponsorFirstName: values[13], - sponsorLastName: values[14], - sponsorEmail: values[15], - reservationTitle: values[16], - reservationDescription: values[17], - expectedAttendance: values[18], - attendeeAffiliation: values[19], - roomSetup: values[20], - setupDetails: values[21], - mediaServices: values[22], - mediaServicesDetails: values[23], - catering: values[24], - cateringService: values[25], - chartfieldInformation: values[26], - hireSecurity: values[27], - }; - }; - - const mappingBookingStatusRow = (values: string[]): BookingStatus => { - return { - calendarEventId: values[0], - email: values[1], - requestedAt: values[2], - firstApprovedAt: values[3], - secondApprovedAt: values[4], - rejectedAt: values[5], - canceledAt: values[6], - checkedInAt: values[7], - }; - }; - - const BookingStatusName = (id) => { - const target = mappingBookingStatuses.filter( - (item) => item.calendarEventId === id - )[0]; - if (target === undefined) return 'Unknown'; - if (target.checkedInAt !== '') { - return 'Checked In'; - } else if (target.canceledAt !== '') { - return 'Canceled'; - } else if (target.rejectedAt !== '') { - return 'Rejected'; - } else if (target.secondApprovedAt !== '') { - return 'Approved'; - } else if (target.firstApprovedAt !== '') { - return 'Pre Approved'; - } else if (target.requestedAt !== '') { - return 'Requested'; - } else { - return 'Unknown'; - } - }; - return (
    @@ -218,232 +80,7 @@ const Admin = () => { {tab === 'ban' && } {tab === 'adminUsers' && } {tab === 'liaesons' && } - {tab === 'bookings' && ( -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - {mappingBookings.map((booking, index) => { - const status = BookingStatusName(booking.calendarEventId); - return ( - - - - - - - - - - - - - - - - - - - - - - - - - - - ); - })} - -
    - Action - - Status - - Room ID - - Name - - Booking Date - - Secondary name - - N number - - Net Id - - Phone number - - Department - - Role - - Sponsor name - - Sponsor email - - Title - - Description - - Expected Attendee - - Attendee Affiliation - - Set up - - Media Service - - Catering - - Catering Service - - Chartfield Information - - Hire security -
    - {status === 'Pre Approved' && ( - - )} - {status === 'Requested' && ( - - )} - - - {status !== 'Checked In' && ( - - )} - {status}{booking.roomId} -
    -
    - -
    -
    - {booking.email} -
    -
    -
    -
    -
    {formatDate(booking.startDate)}
    ~
    -
    {formatDate(booking.endDate)}
    -
    -
    {booking.secondaryName}{booking.nNumber}{booking.netId}{booking.phoneNumber}{booking.department}{booking.role} - {booking.sponsorFirstName} {booking.sponsorLastName} - {booking.sponsorEmail} - {booking.reservationTitle} - - {booking.reservationDescription} - - {booking.expectedAttendance} - - {booking.attendeeAffiliation} - - {booking.roomSetup} - {booking.setupDetails && ( - <> -
    - Details -
    - {booking.setupDetails} - - )} -
    - {booking.mediaServices} - {booking.mediaServicesDetails && ( - <> -
    - Details -
    - {booking.mediaServicesDetails} - - )} -
    {booking.catering} - {booking.cateringService} - - {booking.chartfieldInformation} - {booking.hireSecurity}
    -
    - )} + {tab === 'bookings' && }
); }; diff --git a/media_commons_booking_app/src/client/admin-page/components/Bookings.tsx b/media_commons_booking_app/src/client/admin-page/components/Bookings.tsx new file mode 100644 index 00000000..c0d1b81d --- /dev/null +++ b/media_commons_booking_app/src/client/admin-page/components/Bookings.tsx @@ -0,0 +1,385 @@ +import React, { useState, useEffect } from 'react'; + +// This is a wrapper for google.script.run that lets us use promises. +import { serverFunctions } from '../../utils/serverFunctions'; +import { Inputs } from '../../booking/components/FormInput'; +import { SafetyTraining } from './SafetyTraining'; +import { Ban } from './Ban'; +import { AdminUsers } from './AdminUsers'; +import { Liaisons } from './Liaisons'; +import { formatDate } from '../../utils/date'; + +const BOOKING_SHEET_NAME = 'bookings'; + +type Booking = Inputs & { + calendarEventId: string; + email: string; + startDate: string; + endDate: string; + roomId: string; +}; + +type BookingStatus = { + calendarEventId: string; + email: string; + requestedAt: string; + firstApprovedAt: string; + secondApprovedAt: string; + rejectedAt: string; + canceledAt: string; + checkedInAt: string; +}; + +export const Bookings = () => { + const [bookings, setBookings] = useState([]); + const [mappingBookings, setMappingBookings] = useState([]); + const [mappingBookingStatuses, setMappingBookingStatuses] = useState([]); + const [bookingStatuses, setBookingStatuses] = useState([]); + const [showModal, setShowModal] = useState(false); + const [selectedInfo, setSelectedInfo] = useState(); + const [tab, setTab] = useState('bookings'); + + useEffect(() => { + fetchBookings(); + fetchBookingStatuses(); + }, []); + useEffect(() => { + const mappings = bookings + .map((booking, index) => { + if (index !== 0) { + return mappingBookingRows(booking); + } + }) + .filter((booking) => booking !== undefined); + //TODO: filter out bookings that are not in the future + setMappingBookings(mappings); + }, [bookings]); + + useEffect(() => { + console.log( + bookingStatuses, + 'bookingStatusesbookingStatusesbookingStatusesbookingStatuses' + ); + const mappings = bookingStatuses + .map((bookingStatus, index) => { + console.log(bookingStatus, 'bookingStatus'); + console.log(index, 'index'); + if (index !== 0) { + return mappingBookingStatusRow(bookingStatus); + } + }) + .filter((booking) => booking !== undefined); + console.log('mapping status', mappings); + setMappingBookingStatuses(mappings); + }, [bookingStatuses]); + + const fetchBookings = async () => { + serverFunctions.fetchRows(BOOKING_SHEET_NAME).then((rows) => { + console.log('booking rows', rows); + setBookings(rows); + }); + }; + + const fetchBookingStatuses = async () => { + serverFunctions.fetchRows('bookingStatus').then((statusRows) => { + console.log('bookingStatuses rows', statusRows); + setBookingStatuses(statusRows); + }); + }; + + const mappingBookingRows = (values: string[]): Booking => { + return { + calendarEventId: values[0], + roomId: values[1], + email: values[2], + startDate: values[3], + endDate: values[4], + firstName: values[5], + lastName: values[6], + secondaryName: values[7], + nNumber: values[8], + netId: values[9], + phoneNumber: values[10], + department: values[11], + role: values[12], + sponsorFirstName: values[13], + sponsorLastName: values[14], + sponsorEmail: values[15], + reservationTitle: values[16], + reservationDescription: values[17], + expectedAttendance: values[18], + attendeeAffiliation: values[19], + roomSetup: values[20], + setupDetails: values[21], + mediaServices: values[22], + mediaServicesDetails: values[23], + catering: values[24], + cateringService: values[25], + chartfieldInformation: values[26], + hireSecurity: values[27], + }; + }; + + const mappingBookingStatusRow = (values: string[]): BookingStatus => { + console.log(values, 'values'); + return { + calendarEventId: values[0], + email: values[1], + requestedAt: values[2], + firstApprovedAt: values[3], + secondApprovedAt: values[4], + rejectedAt: values[5], + canceledAt: values[6], + checkedInAt: values[7], + }; + }; + + const BookingStatusName = (id) => { + const target = mappingBookingStatuses.filter( + (item) => item.calendarEventId === id + )[0]; + if (target === undefined) return 'Unknown'; + if (target.checkedInAt !== '') { + return 'Checked In'; + } else if (target.canceledAt !== '') { + return 'Canceled'; + } else if (target.rejectedAt !== '') { + return 'Rejected'; + } else if (target.secondApprovedAt !== '') { + return 'Approved'; + } else if (target.firstApprovedAt !== '') { + return 'Pre Approved'; + } else if (target.requestedAt !== '') { + return 'Requested'; + } else { + return 'Unknown'; + } + }; + + return ( +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {mappingBookings.map((booking, index) => { + const status = BookingStatusName(booking.calendarEventId); + return ( + + + + + + + + + + + + + + + + + + + + + + + + + + + ); + })} + +
+ Action + + Status + + Room ID + + Name + + Booking Date + + Secondary name + + N number + + Net Id + + Phone number + + Department + + Role + + Sponsor name + + Sponsor email + + Title + + Description + + Expected Attendee + + Attendee Affiliation + + Set up + + Media Service + + Catering + + Catering Service + + Chartfield Information + + Hire security +
+ {status === 'Pre Approved' && ( + + )} + {status === 'Requested' && ( + + )} + + + {status !== 'Checked In' && ( + + )} + {status}{booking.roomId} +
+
+ +
+
+ {booking.email} +
+
+
+
+
{formatDate(booking.startDate)}
~
+
{formatDate(booking.endDate)}
+
+
{booking.secondaryName}{booking.nNumber}{booking.netId}{booking.phoneNumber}{booking.department}{booking.role} + {booking.sponsorFirstName} {booking.sponsorLastName} + {booking.sponsorEmail} + {booking.reservationTitle} + + {booking.reservationDescription} + + {booking.expectedAttendance} + + {booking.attendeeAffiliation} + + {booking.roomSetup} + {booking.setupDetails && ( + <> +
+ Details +
+ {booking.setupDetails} + + )} +
+ {booking.mediaServices} + {booking.mediaServicesDetails && ( + <> +
+ Details +
+ {booking.mediaServicesDetails} + + )} +
{booking.catering}{booking.cateringService} + {booking.chartfieldInformation} + {booking.hireSecurity}
+
+
+ ); +}; From 794e65ed4bed015e08836a05a03f159518a18363 Mon Sep 17 00:00:00 2001 From: "riho.takagi" Date: Mon, 23 Oct 2023 16:10:38 -0400 Subject: [PATCH 2/4] remove button --- .../admin-page/components/AdminUsers.tsx | 54 ++++++++++------ .../src/client/admin-page/components/Ban.tsx | 21 ++++++- .../client/admin-page/components/Liaisons.tsx | 62 +++++++++++++++++-- .../admin-page/components/SafetyTraining.tsx | 19 ++++++ media_commons_booking_app/src/server/admin.js | 8 ++- media_commons_booking_app/src/server/index.ts | 4 +- 6 files changed, 141 insertions(+), 27 deletions(-) diff --git a/media_commons_booking_app/src/client/admin-page/components/AdminUsers.tsx b/media_commons_booking_app/src/client/admin-page/components/AdminUsers.tsx index 10ddc690..f0a48d5e 100644 --- a/media_commons_booking_app/src/client/admin-page/components/AdminUsers.tsx +++ b/media_commons_booking_app/src/client/admin-page/components/AdminUsers.tsx @@ -2,13 +2,13 @@ import React, { useState, useEffect } from 'react'; // This is a wrapper for google.script.run that lets us use promises. import { serverFunctions } from '../../utils/serverFunctions'; -import { formatDate } from '@fullcalendar/core'; +import { formatDate } from '../../utils/date'; -const SAFETY_TRAINING_SHEET_NAME = 'admin_users'; +const ADMIN_USER_SHEET_NAME = 'admin_users'; -type SafetyTraining = { +type AdminUser = { email: string; - completedAt: string; + createdAt: string; }; export const AdminUsers = () => { @@ -22,12 +22,12 @@ export const AdminUsers = () => { }, []); useEffect(() => { const mappings = adminUsers - .map((safetyTraining, index) => { + .map((adminUser, index) => { if (index !== 0) { - return mappingSafetyTrainingRows(safetyTraining); + return mappingAdminUserRows(adminUser); } }) - .filter((safetyTraining) => safetyTraining !== undefined); + .filter((adminUser) => adminUser !== undefined); //TODO: filter out adminUsers that are not in the future setMappingAdminUsers(mappings); const emails = mappings.map((mapping) => { @@ -37,31 +37,31 @@ export const AdminUsers = () => { }, [adminUsers]); const fetchAdminUsers = async () => { - serverFunctions.fetchRows(SAFETY_TRAINING_SHEET_NAME).then((rows) => { + serverFunctions.fetchRows(ADMIN_USER_SHEET_NAME).then((rows) => { setAdminUsers(rows); }); }; - const mappingSafetyTrainingRows = (values: string[]): SafetyTraining => { + const mappingAdminUserRows = (values: string[]): AdminUser => { return { email: values[0], - completedAt: values[1], + createdAt: values[1], }; }; - console.log('adminEmails', adminEmails); - const addSafetyTrainingUser = () => { + const addAdminUser = () => { if (adminEmails.includes(email)) { alert('This user is already registered'); return; } - serverFunctions.appendRow(SAFETY_TRAINING_SHEET_NAME, [ + serverFunctions.appendRow(ADMIN_USER_SHEET_NAME, [ email, new Date().toString(), ]); alert('User has been registered successfully!'); + window.location.reload(); }; return (
@@ -86,7 +86,7 @@ export const AdminUsers = () => {
+ ); })} diff --git a/media_commons_booking_app/src/client/admin-page/components/Ban.tsx b/media_commons_booking_app/src/client/admin-page/components/Ban.tsx index 99024254..cbb8dffa 100644 --- a/media_commons_booking_app/src/client/admin-page/components/Ban.tsx +++ b/media_commons_booking_app/src/client/admin-page/components/Ban.tsx @@ -58,6 +58,7 @@ export const Ban = () => { serverFunctions.appendRow(BAN_SHEET_NAME, [email, new Date().toString()]); alert('User has been registered successfully!'); + window.location.reload(); }; return (
@@ -99,6 +100,9 @@ export const Ban = () => { Ban Date + + Action + @@ -111,9 +115,24 @@ export const Ban = () => { {ban.email}
-
{formatDate(ban.completedAt)}
{' '} +
{formatDate(ban.bannedAt)}
{' '}
+ + + ); })} diff --git a/media_commons_booking_app/src/client/admin-page/components/Liaisons.tsx b/media_commons_booking_app/src/client/admin-page/components/Liaisons.tsx index c42f06cb..70074a3f 100644 --- a/media_commons_booking_app/src/client/admin-page/components/Liaisons.tsx +++ b/media_commons_booking_app/src/client/admin-page/components/Liaisons.tsx @@ -4,7 +4,7 @@ import React, { useState, useEffect } from 'react'; import { serverFunctions } from '../../utils/serverFunctions'; import { formatDate } from '../../utils/date'; -const SHEET_NAME = 'liaisons'; +const LIAISON_SHEET_NAME = 'liaisons'; type LiaisonType = { email: string; @@ -17,6 +17,7 @@ export const Liaisons = () => { const [liaisonEmails, setAdminEmails] = useState([]); const [mappingLiaisonUsers, setMappingLiaisonUsers] = useState([]); const [email, setEmail] = useState(''); + const [department, setDepartment] = useState(''); useEffect(() => { fetchLiaisonUsers(); @@ -38,7 +39,7 @@ export const Liaisons = () => { }, [liaisonUsers]); const fetchLiaisonUsers = async () => { - serverFunctions.fetchRows(SHEET_NAME).then((rows) => { + serverFunctions.fetchRows(LIAISON_SHEET_NAME).then((rows) => { setLiaisonUsers(rows); }); }; @@ -52,15 +53,25 @@ export const Liaisons = () => { }; console.log('liaisonEmails', liaisonEmails); - const addSafetyTrainingUser = () => { + const addLiaisonUser = () => { + if (email === '' || department === '') { + alert('Please fill in all the fields'); + return; + } + if (liaisonEmails.includes(email)) { alert('This user is already registered'); return; } - serverFunctions.appendRow(SHEET_NAME, [email, new Date().toString()]); + serverFunctions.appendRow(LIAISON_SHEET_NAME, [ + email, + department, + new Date().toString(), + ]); alert('User has been registered successfully!'); + window.location.reload(); }; return (
@@ -83,9 +94,30 @@ export const Liaisons = () => { required />
+
+ +
+ + + ); })} diff --git a/media_commons_booking_app/src/client/admin-page/components/SafetyTraining.tsx b/media_commons_booking_app/src/client/admin-page/components/SafetyTraining.tsx index 86d15b67..02f08279 100644 --- a/media_commons_booking_app/src/client/admin-page/components/SafetyTraining.tsx +++ b/media_commons_booking_app/src/client/admin-page/components/SafetyTraining.tsx @@ -62,6 +62,7 @@ export const SafetyTraining = () => { ]); alert('User has been registered successfully!'); + window.location.reload(); }; return (
@@ -103,6 +104,9 @@ export const SafetyTraining = () => { Completed Date + + action + @@ -118,6 +122,21 @@ export const SafetyTraining = () => {
{formatDate(safetyTraining.completedAt)}
{' '}
+ + + ); })} diff --git a/media_commons_booking_app/src/server/admin.js b/media_commons_booking_app/src/server/admin.js index 5ed97500..8117ce4c 100644 --- a/media_commons_booking_app/src/server/admin.js +++ b/media_commons_booking_app/src/server/admin.js @@ -1,4 +1,3 @@ -export const ACTIVE_SHEET_ID = '1VZ-DY6o0GM5DL-v9AKkpCbF0w-xm-_T-vVUSPZph06Q'; export const BOOKING_SHEET_NAME = 'bookings'; export const BOOKING_STATUS_SHEET_NAME = 'bookingStatus'; const SECOND_APPROVER_EMAIL = 'rh3555@nyu.edu'; @@ -167,3 +166,10 @@ export const checkin = (id) => { .setValue(current); updateEventPrefix(id, 'CHECKED IN'); }; + +export const removeFromList = (sheet_name, email) => { + const rowIndex = fetchRows_(sheet_name).findIndex((row) => row[0] === email); + SpreadsheetApp.openById(ACTIVE_SHEET_ID) + .getSheetByName(sheet_name) + .deleteRow(rowIndex + 1); +}; diff --git a/media_commons_booking_app/src/server/index.ts b/media_commons_booking_app/src/server/index.ts index 71d9a437..279d0c56 100644 --- a/media_commons_booking_app/src/server/index.ts +++ b/media_commons_booking_app/src/server/index.ts @@ -16,9 +16,9 @@ import { cancel, checkin, approveInstantBooking, - ACTIVE_SHEET_ID, BOOKING_STATUS_SHEET_NAME, BOOKING_SHEET_NAME, + removeFromList, } from './admin'; import { @@ -31,6 +31,7 @@ import { addEventToCalendar, getEvents, getSheetRows, + ACTIVE_SHEET_ID, confirmEvent, approvedByFirstPerson, approvedBySecondPerson, @@ -73,4 +74,5 @@ export { BOOKING_SHEET_NAME, getGoogleCalendarApiKey, getUserEmail, + removeFromList, }; From 4c7868cb5b2858f0e04e24dd801152adfcfbce7b Mon Sep 17 00:00:00 2001 From: "riho.takagi" Date: Mon, 23 Oct 2023 16:11:12 -0400 Subject: [PATCH 3/4] updated text --- .../client/booking/components/Calendars.tsx | 11 +-- .../client/booking/components/FormInput.tsx | 95 ++++++++----------- .../client/booking/components/SheetEditor.tsx | 9 +- .../src/server/sheets.js | 2 +- 4 files changed, 44 insertions(+), 73 deletions(-) diff --git a/media_commons_booking_app/src/client/booking/components/Calendars.tsx b/media_commons_booking_app/src/client/booking/components/Calendars.tsx index b3cfc8aa..58bdbcc7 100644 --- a/media_commons_booking_app/src/client/booking/components/Calendars.tsx +++ b/media_commons_booking_app/src/client/booking/components/Calendars.tsx @@ -46,12 +46,11 @@ export const Calendars = ({ } if (bookInfo) { const isConfirmed = window.confirm( - `You are booking the following rooms: ${selectedRooms.map( + `You are requesting to book the following rooms${selectedRooms.map( (room) => `${room.roomId} ${room.name}` - )} - \nYour reserved time slot: ${formatDate( - bookInfo.startStr - )} ~ ${formatDate(bookInfo.endStr)}` + )} for the time slot ${formatDate(bookInfo.startStr)} ~ ${formatDate( + bookInfo.endStr + )}` ); if (isConfirmed) handleSetDate(bookInfo); } @@ -115,7 +114,7 @@ export const Calendars = ({ id: Date.now(), // Generate a unique ID for the event start: selectInfo.startStr, end: selectInfo.endStr, - title: `${TITLE_TAG} Reserve`, + title: `${TITLE_TAG}`, groupId: selectInfo.startStr, }); }); diff --git a/media_commons_booking_app/src/client/booking/components/FormInput.tsx b/media_commons_booking_app/src/client/booking/components/FormInput.tsx index d26c64fb..d3a72260 100644 --- a/media_commons_booking_app/src/client/booking/components/FormInput.tsx +++ b/media_commons_booking_app/src/client/booking/components/FormInput.tsx @@ -68,6 +68,8 @@ const FormInput = ({ hasEmail, roomNumber, handleParentSubmit }) => { const [agreement, setAgreement] = useState(false); const [resetRoom, setResetRoom] = useState(false); const [bookingPolicy, setBookingPolicy] = useState(false); + const [showTextbox, setShowTextbox] = useState(false); + const disabledButton = !( checklist && agreement && @@ -86,6 +88,14 @@ const FormInput = ({ hasEmail, roomNumber, handleParentSubmit }) => { }; console.log('errors', errors); + const handleSelectChange = (event) => { + if (event.target.value === 'others') { + setShowTextbox(true); + } else { + setShowTextbox(false); + } + }; + return (
{ required: true, validate: (value) => value !== '', })} + onChange={(e) => { + handleSelectChange(e); + }} > - {watch('department') === 'others' && ( + {showTextbox && ( { id="sponsorFirstName" className="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-[600px] p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" placeholder="" - {...register('sponsorFirstName')} + {...register('sponsorFirstName', { + required: watch('role') === 'Student', + })} />
@@ -347,7 +362,9 @@ const FormInput = ({ hasEmail, roomNumber, handleParentSubmit }) => { id="sponsorLastName" className="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-[600px] p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" placeholder="" - {...register('sponsorLastName')} + {...register('sponsorLastName', { + required: watch('role') === 'Student', + })} />
@@ -367,6 +384,7 @@ const FormInput = ({ hasEmail, roomNumber, handleParentSubmit }) => { className="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-[600px] p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" placeholder="" {...register('sponsorEmail', { + required: watch('role') === 'Student', pattern: { value: /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i, message: 'Invalid email address', @@ -522,12 +540,17 @@ const FormInput = ({ hasEmail, roomNumber, handleParentSubmit }) => { formation.

+ {errors.setupDetails && ( + + )}
)} @@ -663,8 +686,16 @@ const FormInput = ({ hasEmail, roomNumber, handleParentSubmit }) => { Catering Information

- Including catering in your event necessitates hiring CBS cleaning - services. + It is required for the reservation holder to pay and arrange for CBS + cleaning services if the event includes catering. + + Please see this link for more information + + .

-
- - )}
-
- -
- setAgreement(!agreement)} - className="w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600" - /> - -
-