kids and booking forms, instructions
This commit is contained in:
parent
e9b71f1993
commit
58ffa8622b
26
README.md
26
README.md
@ -1,3 +1,27 @@
|
||||
# MemberPortal
|
||||
|
||||
Client for MemberService, used to manage member accounts at member site.
|
||||
Client for MemberService, used to manage member accounts at member site.
|
||||
|
||||
## Installation
|
||||
|
||||
`npm install`
|
||||
|
||||
## Build and Deploy
|
||||
|
||||
In app.jsx switch to the URL of the live service.
|
||||
|
||||
`npm run build`
|
||||
|
||||
This will output to the dist folder one directory above.
|
||||
Transfer that build folder to the server.
|
||||
|
||||
`scp -r -i ~/Documents/wowza-keys.pem dist ubuntu@107.20.181.47:/home/ubuntu/dist`
|
||||
|
||||
If in doubt, you can remove the dist folder on the server to ensure this is a fresh build.
|
||||
|
||||
`rm -r dist`
|
||||
|
||||
On the server, start the staticserver:
|
||||
|
||||
`nodemon staticserver.js`
|
||||
|
||||
|
69
src/App.jsx
69
src/App.jsx
@ -2,6 +2,8 @@ import React, { useState, useEffect } from "react";
|
||||
import { format, addMonths } from "date-fns"; // Import date-fns for formatting
|
||||
import LockerRentalForm from "./lockerRentalForm.jsx"
|
||||
import CertificationAssignmentForm from "./certAssignmentForm.jsx"
|
||||
import StorageBookingForm from "./storagebookingform.jsx";
|
||||
import KidsProgramEnrollmentForm from "./kidsprogramform.jsx";
|
||||
import Button from "./button.jsx";
|
||||
import './index.css'
|
||||
|
||||
@ -9,8 +11,8 @@ function App() {
|
||||
const queryParams = new URLSearchParams(window.location.search);
|
||||
const uuid = queryParams.get("uuid");
|
||||
const [data, setData] = useState([]);
|
||||
// const SERVICE_URL = 'https://service.ttlmakerspace.com';
|
||||
const SERVICE_URL = 'http://localhost:3000';
|
||||
const SERVICE_URL = 'https://service.ttlmakerspace.com';
|
||||
//const SERVICE_URL = 'http://localhost:3000';
|
||||
|
||||
if(uuid){
|
||||
useEffect(() => {
|
||||
@ -145,6 +147,58 @@ function App() {
|
||||
console.error("Error saving date:", error);
|
||||
}
|
||||
}
|
||||
const handleStorageBooking =async (storage)=>{
|
||||
console.log(storage)
|
||||
try {
|
||||
const response = await fetch(SERVICE_URL+"/member/storage/"+uuid, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify(storage),
|
||||
});
|
||||
|
||||
const responseData = await response.json();
|
||||
|
||||
if (response.ok) {
|
||||
let cleanData = {...data};
|
||||
cleanData.storage = storage;
|
||||
setData(cleanData)
|
||||
} else {
|
||||
console.log("Failed to save data: " + (responseData.error || "Unknown error"));
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error saving date:", error);
|
||||
}
|
||||
}
|
||||
const handleKidEnrollment =async (kid)=>{
|
||||
console.log(kid)
|
||||
console.log(data.jwb)
|
||||
const allKids = data.jwb
|
||||
allKids.push(kid)
|
||||
let cleanData = {...data};
|
||||
cleanData.jwb = allKids;
|
||||
console.log(cleanData)
|
||||
try {
|
||||
const response = await fetch(SERVICE_URL+"/member/jwb/"+uuid, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify(allKids),
|
||||
});
|
||||
|
||||
const responseData = await response.json();
|
||||
|
||||
if (response.ok) {
|
||||
setData(cleanData)
|
||||
} else {
|
||||
console.log("Failed to save data: " + (responseData.error || "Unknown error"));
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error saving date:", error);
|
||||
}
|
||||
}
|
||||
if(uuid){
|
||||
return (
|
||||
<>
|
||||
@ -161,16 +215,19 @@ function App() {
|
||||
|
||||
<div className="max-w-md mx-auto p-6 bg-white shadow-md rounded-lg">
|
||||
{data.jwb ? (<><h3 className="text-xl font-semibold mb-4">Junior WorldBuilders:</h3>
|
||||
<ul>
|
||||
<KidsProgramEnrollmentForm onSubmit={handleKidEnrollment} />
|
||||
|
||||
{data.jwb.map((kid) => (
|
||||
<li key={kid.name}>{kid.name}</li>
|
||||
<li key={kid.childName}>{kid.childName}<br />{kid.program} Start Date: {format(addMonths(new Date(kid.startDate),1), "yyyy-MM-dd")}</li>
|
||||
))}
|
||||
</ul></>) : (<p>No Kids</p>)}
|
||||
</>) : (<p>No Kids</p>)}
|
||||
|
||||
</div>
|
||||
|
||||
<div className="max-w-md mx-auto p-6 bg-white shadow-md rounded-lg">
|
||||
{data.storage ? (<h4 className="text-xl font-semibold mb-4">Large Storage</h4>):(<></>)}
|
||||
{data.storage ? (<p>Date Issued: {format(new Date(data.storage.dateIssued), "yyyy-MM-dd")}</p>):(<></>)}
|
||||
{data.storage ? (<p>Date Issued: {format(new Date(data.storage.startDate), "yyyy-MM-dd")}</p>):(<></>)}
|
||||
<StorageBookingForm onSubmit={handleStorageBooking} />
|
||||
</div>
|
||||
|
||||
<div className="max-w-md mx-auto p-6 bg-white shadow-md rounded-lg">
|
||||
|
@ -11,7 +11,7 @@ const CertificationAssignmentForm = ({ onSubmit }) => {
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="max-w-md mx-auto p-6 bg-white shadow-md rounded-lg">
|
||||
<div className="outline-red-300 outline-dashed outline-4 outline-offset-2 max-w-md mx-auto p-6 bg-white shadow-md rounded-lg">
|
||||
<h2 className="text-xl font-semibold mb-4">Assign Certification</h2>
|
||||
<form onSubmit={handleSubmit(handleFormSubmit)}>
|
||||
<div className="mb-4">
|
||||
|
70
src/kidsprogramform.jsx
Normal file
70
src/kidsprogramform.jsx
Normal file
@ -0,0 +1,70 @@
|
||||
import React, { useState } from "react";
|
||||
import { useForm, Controller } from "react-hook-form";
|
||||
import DatePicker from "react-datepicker";
|
||||
import "react-datepicker/dist/react-datepicker.css";
|
||||
import { RadioGroup, Radio } from "@headlessui/react";
|
||||
|
||||
const programs = [
|
||||
{ name: "Junior Worldbuilders" },
|
||||
{ name: "Young Worldbuilders" },
|
||||
];
|
||||
|
||||
const Field = ({ children }) => (
|
||||
<div className="p-2 border rounded cursor-pointer">{children}</div>
|
||||
);
|
||||
|
||||
const KidsProgramEnrollmentForm = ({ onSubmit }) => {
|
||||
const { handleSubmit, control, register } = useForm();
|
||||
const [selectedProgram, setSelectedProgram] = useState(programs[0].name);
|
||||
|
||||
const handleFormSubmit = (data) => {
|
||||
const requestData = { ...data, program: selectedProgram };
|
||||
onSubmit(requestData);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="outline-red-300 outline-dashed outline-4 outline-offset-2 max-w-md mx-auto p-6 bg-white shadow-md rounded-lg">
|
||||
<h2 className="text-xl font-semibold mb-4">Enroll in Kids Program</h2>
|
||||
<form onSubmit={handleSubmit(handleFormSubmit)}>
|
||||
<div className="mb-4">
|
||||
<label className="block text-sm font-medium">Child's Name</label>
|
||||
<input
|
||||
type="text"
|
||||
{...register("childName", { required: true })}
|
||||
className="border p-2 rounded w-full"
|
||||
placeholder="Enter child's name"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="mb-4">
|
||||
<label className="block text-sm font-medium">Start Date</label>
|
||||
<Controller
|
||||
name="startDate"
|
||||
control={control}
|
||||
defaultValue={new Date()}
|
||||
render={({ field }) => (
|
||||
<DatePicker className="border p-2 rounded w-full" selected={field.value} onChange={field.onChange} />
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="mb-4">
|
||||
<label className="block text-sm font-medium">Program Selection</label>
|
||||
<RadioGroup value={selectedProgram} onChange={setSelectedProgram} className="mt-2">
|
||||
{programs.map(({ name }) => (
|
||||
<Field key={name}>
|
||||
<Radio value={name} className="flex items-center space-x-2 p-2 border rounded cursor-pointer data-[checked]:bg-blue-400 data-[disabled]:bg-gray-100">
|
||||
<span>{name}</span>
|
||||
</Radio>
|
||||
</Field>
|
||||
))}
|
||||
</RadioGroup>
|
||||
</div>
|
||||
|
||||
<button type="submit" className="w-full p-2 bg-blue-500 text-white rounded">Enroll</button>
|
||||
</form>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default KidsProgramEnrollmentForm;
|
37
src/storagebookingform.jsx
Normal file
37
src/storagebookingform.jsx
Normal file
@ -0,0 +1,37 @@
|
||||
import React from "react";
|
||||
import { useForm, Controller } from "react-hook-form";
|
||||
import DatePicker from "react-datepicker";
|
||||
import "react-datepicker/dist/react-datepicker.css";
|
||||
|
||||
const StorageBookingForm = ({ onSubmit }) => {
|
||||
const { handleSubmit, control } = useForm();
|
||||
|
||||
const handleFormSubmit = (data) => {
|
||||
onSubmit(data);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="outline-red-300 outline-dashed outline-4 outline-offset-2 max-w-md mx-auto p-6 bg-white shadow-md rounded-lg">
|
||||
<h2 className="text-xl font-semibold mb-4">Book Storage Space</h2>
|
||||
<form onSubmit={handleSubmit(handleFormSubmit)}>
|
||||
<div className="mb-4">
|
||||
<label className="block text-sm font-medium">Start Date</label>
|
||||
<Controller
|
||||
name="startDate"
|
||||
control={control}
|
||||
defaultValue={new Date()}
|
||||
render={({ field }) => (
|
||||
<DatePicker className="border p-2 rounded w-full" selected={field.value} onChange={field.onChange} />
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<button type="submit" className="w-full p-2 bg-blue-500 text-white rounded">
|
||||
Book Storage
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default StorageBookingForm;
|
Loading…
Reference in New Issue
Block a user