Skip to content

Instantly share code, notes, and snippets.

@MonteLogic
Created April 30, 2024 18:10
Show Gist options
  • Save MonteLogic/798f8b9429449425f782a50afe2628c7 to your computer and use it in GitHub Desktop.
Save MonteLogic/798f8b9429449425f782a50afe2628c7 to your computer and use it in GitHub Desktop.
'use client';
import { useState, MouseEventHandler, useEffect } from 'react'; // Import MouseEventHandler
import Button from './button';
import { updateSummary, createRecordForSummary } from '#/app/utils/network-fns';
import TextareaAutosize from 'react-textarea-autosize';
import { UploadButton } from '#/app/utils/uploadthing';
import { ImageString } from './image-slider';
import StandardModal from './standard-modal';
import { FormattedRouteType } from '#/types/RouteTypes';
import { useSearchParams, usePathname, useRouter } from 'next/navigation';
import ConfirmingButton from './confirming-button';
interface WorkTimeObjectSummary {
earlyMorning?: { text?: string; imgURLs?: string[] }[];
midMorning?: { text?: string; imgURLs?: string[] }[];
midDay?: { text?: string; imgURLs?: string[] }[];
afternoon?: { text?: string; imgURLs?: string[] }[];
}
// I don't even need that routeIDs API call stuff when I can just pipe it in from the server component.
// But how will we get new information from that server component like we can with an API call.
export const SummarySelection = ({
initRoutes,
}: {
initRoutes: FormattedRouteType;
}) => {
const [dateSelection, setDateSelection] = useState(
new Date().toISOString().split('T')[0],
); // Set the initial date format to match the input type
const [routeIDFromURL, setRouteIDFromURL] = useState<string | null>(null);
const [routeIDs, setRouteIDs] = useState(initRoutes); // Add the 'routes' property with an empty array as the default value
const [summaryObject, setSummaryObject] =
useState<WorkTimeObjectSummary | null>(null); // Initialize with null
const [entryID, setEntryID] = useState<string | null>(null); // State to hold the new summary value
const [currentPORoute, setCurrentPORoute] = useState<string | null>(null); // State to hold the new summary value
const searchParams = useSearchParams();
const pathname = usePathname();
const { replace } = useRouter();
console.log(42, entryID);
const RouteSelect = () => {
const defaultValue = searchParams.get('route')?.toString();
const handleChange = (e: any) => {
const selectedRoute = e.target.value;
setSearchURL(dateSelection, selectedRoute);
setRouteIDFromURL(selectedRoute);
searchForSummary(dateSelection, selectedRoute ?? '');
};
return (
<select
className="text-gray-900"
id="routes"
name="routes"
value={routeIDFromURL ?? ''}
defaultValue={defaultValue}
onChange={handleChange}
>
{routeIDs.length > 0 ? (
routeIDs.map((route: any) => (
<option key={route[0]} value={route[0]}>
{`${route[0]}-${route[1]}`}
</option>
))
) : (
<option value="No routes found">No routes found</option>
)}
</select>
);
};
// Route is set but not by default, let's make it default.
const setSearchURL = (date: string, route: string) => {
console.log(62, date);
const params = new URLSearchParams(searchParams);
if (date) {
params.set('date', date);
} else {
params.delete('date');
}
if (route) {
params.set('route', route);
} else {
params.delete('route');
}
replace(`${pathname}?${params.toString()}`);
};
const searchForSummary = async (date: string, routeID: string) => {
try {
const response = await fetch(
`/api/search-shift?date=${date}&routeID=${routeID}`,
{
method: 'GET',
headers: {
'Content-Type': 'application/json',
},
},
);
if (response.ok) {
const data = await response.json();
const receivedID = data['id'];
if (receivedID) {
setEntryID(receivedID);
}
if (!receivedID) {
setEntryID(null);
}
const field = data?.field?.[0]?.summary?.earlyMorning || [];
const routeIDCurrent = data?.field?.[0]?.routeIDFromPostOffice || [];
const fullSummaryResponse = data?.field?.[0]?.summary || [];
setCurrentPORoute(routeIDCurrent);
console.log(107, currentPORoute);
if (fullSummaryResponse) {
console.log(111, fullSummaryResponse);
// Update the state with the fetched route summary
setSummaryObject(fullSummaryResponse); // Set the summaryObject state with the fullSummaryResponse
} else {
console.error('No route summary found');
}
const routeSummaryResponse = field || [];
console.log(87.1, routeSummaryResponse);
return 'Has updated'; // It's better to return a value rather than a string
} else {
// Error occurred while updating work time
console.log('Could not find matching day, setting empty object.'); // Update search result state
setSummaryObject({}); // Set the summaryObject state with an empty object
setEntryID(null);
console.error('Error updating work time');
}
} catch (error) {
console.error('Error updating work time', error);
alert('Error viewing work time');
}
};
// This could be a variable in a different file, and still need judger in this file to judge whether
// or not to display the relevant shifts.
const routeComponents = [
{
shiftNiceName: 'Early Morning',
shiftName: 'earlyMorning',
},
{
shiftNiceName: 'Mid Morning',
shiftName: 'midMorning',
},
{
shiftNiceName: 'Mid Day',
shiftName: 'midDay',
},
{
shiftNiceName: 'Afternoon',
shiftName: 'afternoon',
},
];
function getActiveShifts(id: string, index: number): void {
const shifts = routeIDs[index];
const location = shifts?.find((entry: any) => entry[0] === id);
if (!location) {
console.log('Location not found.');
return;
}
// @ts-ignore
const shiftInfo = location[2];
if (!shiftInfo) {
console.log('No shift information available for this location.');
return;
}
// @ts-ignore
const activeShifts = Object.entries(shiftInfo.allocatedShifts).filter(
// @ts-ignore
([_, shift]) => shift.active === 1,
);
}
const summaryObjectFunc = (summaryObject: any) => {
if (!summaryObject) {
return null;
}
return (
<>
{routeComponents.map((routeComponent, index) => {
const key = `${routeComponent.shiftName}-${index}`; // Generate a unique key
const shifts = routeIDs[index];
// if (routeIDs.routes[i][0] === routeID) {
// Example usage:
getActiveShifts(currentPORoute as string, index);
return (
<div key={key}>
<p>Shift: {routeComponent.shiftNiceName}</p>
<TextareaAutosize
className="text-gray-900"
id="newSummaryInputID"
name="newSummaryInputName"
minRows={3}
// This is WorkTime info but I think it's only showing summary stuff.
value={
(summaryObject &&
(summaryObject as WorkTimeObjectSummary)[
routeComponent.shiftName as keyof WorkTimeObjectSummary
]?.[0]?.text) ||
''
}
onChange={(e) => {
setSummaryObject(
(prevSummaryObject: WorkTimeObjectSummary | null) => ({
...prevSummaryObject,
[routeComponent.shiftName as keyof WorkTimeObjectSummary]:
[
{
text: e.target.value || '',
imgURLs:
(prevSummaryObject &&
prevSummaryObject[
routeComponent.shiftName as keyof WorkTimeObjectSummary
]?.[0]?.imgURLs) ||
[],
},
],
}),
);
}}
/>
{(summaryObject as WorkTimeObjectSummary)[
routeComponent.shiftName as keyof WorkTimeObjectSummary
]?.[0] ? (
<ImageString
imgStringArray={
(summaryObject as WorkTimeObjectSummary)[
routeComponent.shiftName as keyof WorkTimeObjectSummary
]?.[0]?.imgURLs?.map((image) => image) ?? []
}
/>
) : (
<div>
<p>No images</p>
</div>
)}
<UploadButton
endpoint="imageUploader"
content={{
button({ ready }) {
if (ready)
return (
<div>
Upload Image for {routeComponent.shiftNiceName} Shift
</div>
);
return 'Getting ready...';
},
allowedContent({ ready, fileTypes, isUploading }) {
if (!ready) return 'Checking what you allow';
if (isUploading) return 'Seems like stuff is uploading';
return `Stuff you can upload: ${fileTypes.join(', ')}`;
},
}}
onClientUploadComplete={(res) => {
// Do something with the response
console.log('Files: ', res);
console.log(346, res[0].url);
if (res[0].url) {
setSummaryObject(
(prevSummaryObject: WorkTimeObjectSummary | null) => {
const updatedObject = { ...prevSummaryObject };
const shiftName =
routeComponent.shiftName as keyof WorkTimeObjectSummary;
// Check if the shiftName already exists in the ObjectSummary
if (updatedObject.hasOwnProperty(shiftName)) {
// Find the object corresponding to the shiftName
const existingArray = updatedObject[shiftName] as {
text: string;
imgURLs?: string[];
}[];
// Update the imgURLs array within the object
updatedObject[shiftName] = existingArray.map(
(item) => ({
...item,
imgURLs: [...(item.imgURLs || []), res[0].url],
}),
);
} else {
// If the shiftName doesn't exist, initialize it with a new array containing the new URL
updatedObject[shiftName] = [
{ imgURLs: [res[0].url] },
];
}
// Call updateSummaryObject after setting the updated state
updateSummaryObject();
return updatedObject;
},
);
// Run the function updateSummaryObject to save the new image URL
alert('Upload Completed');
}
}}
onUploadError={(error: Error) => {
// Do something with the error.
alert(`ERROR! ${error.message}`);
}}
/>
</div>
);
})}
<ConfirmingButton
onClick={updateSummaryObject}
disabled={saveEditedClicked}
>
{saveEditedClicked ? 'Saving...' : 'Save Edited Stuff'}
</ConfirmingButton>
</>
);
};
const [saveEditedClicked, setSaveEditedClicked] = useState(false);
const updateSummaryObject: any = async () => {
setSaveEditedClicked(true); // Button has been clicked
setTimeout(() => {
setSaveEditedClicked(false); // Reset button after 1000 milliseconds (1 second)
}, 1000);
if (summaryObject) {
if (entryID) {
updateSummary(
entryID,
dateSelection ?? '',
routeIDFromURL ?? '',
setSummaryObject,
summaryObject,
);
}
if (!entryID) {
createRecordForSummary(
dateSelection ?? '',
routeIDFromURL ?? '',
setSummaryObject,
summaryObject,
);
}
}
};
useEffect(() => {
const currentDate = new Date().toISOString().split('T')[0];
searchForSummary(currentDate, routeIDFromURL ?? '');
}, []);
const [clicked, setClicked] = useState(false);
const viewResults = async (event: React.FormEvent<HTMLFormElement>) => {
// Here I want to pass the value of the input of the date.
setSearchURL(dateSelection, routeIDFromURL ?? '');
event.preventDefault();
searchForSummary(dateSelection ?? '', routeIDFromURL ?? ''); // Pass dateSelection instead of formData.date
setClicked(true); // Button has been clicked
setTimeout(() => {
setClicked(false); // Reset button after 1000 milliseconds (1 second)
}, 1000);
};
const [modalIsOpen, setModalIsOpen] = useState(false);
const closeModal = () => {
setModalIsOpen(false);
};
return (
<>
<div>
{modalIsOpen && (
// I could have workTimeTop up here and then just watch for
// a change in workTimeEmployee and then just change the whole of
// work time top.
<StandardModal
setIsOpen={setModalIsOpen}
// employeeName={selectedEmployeeName}
// employeeID={selectedEmployeeID}
isOpen={modalIsOpen}
closeModal={closeModal}
/>
)}
</div>
<div>
<div className="space-y-1">
<label htmlFor="dateID" className="block">
Date to search:
</label>
<input
className="text-gray-900"
type="date"
id="dateID"
name="date"
value={dateSelection}
onChange={(e) => {
setSearchURL(e.target.value, routeIDFromURL ?? '');
setDateSelection(e.target.value);
}}
defaultValue={searchParams.get('date')?.toString()}
/>
<label htmlFor="routes" className="block">
Choose a route:
</label>
{RouteSelect()}
<ConfirmingButton
onClick={
viewResults as unknown as MouseEventHandler<HTMLButtonElement>
}
disabled={clicked} // Disable the button if it has been clicked
>
{clicked ? 'Searching...' : 'View Summary of Day'}
</ConfirmingButton>
</div>
{summaryObjectFunc(summaryObject)}
</div>
</>
);
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment