-
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 #132 from tritonuas/feat/targetMatch
Manual Target Match
- Loading branch information
Showing
6 changed files
with
260 additions
and
3 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
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,77 @@ | ||
.flex-box { | ||
display: flex; | ||
flex:19; | ||
justify-content: center; | ||
justify-items: center; | ||
align-content: center; | ||
align-items: center; | ||
width: 100%; | ||
height: 100%; | ||
} | ||
|
||
.form-container { | ||
background-color: goldenrod; | ||
border-radius: 20px; | ||
padding: 20px; | ||
text-align: center; | ||
} | ||
|
||
.bottle { | ||
display: flex; | ||
align-items: center; | ||
gap: 30px; | ||
} | ||
|
||
.input-field { | ||
margin: 30px 0; | ||
font-size: 60px; | ||
padding: 10px; | ||
width: 350px; | ||
border: 1px solid rgb(253, 76, 0, 0.5); | ||
border-top: none; | ||
border-left: none; | ||
border-right: none; | ||
background: rgba(20, 20, 20, .2); | ||
color: white; | ||
outline: none; | ||
caret-color: black; | ||
} | ||
|
||
.submit-button { | ||
background-color: initial; | ||
background-image: linear-gradient(-180deg, #FF7E31, #E62C03); | ||
border-radius: 6px; | ||
box-shadow: rgba(0, 0, 0, 0.1) 0 2px 4px; | ||
color: #FFFFFF; | ||
cursor: pointer; | ||
display: inline-block; | ||
font-family: Inter,-apple-system,system-ui,Roboto,"Helvetica Neue",Arial,sans-serif; | ||
font-size: x-large; | ||
height: 60px; | ||
line-height: 40px; | ||
outline: 0; | ||
overflow: hidden; | ||
padding: 0 20px; | ||
pointer-events: auto; | ||
position: relative; | ||
text-align: center; | ||
touch-action: manipulation; | ||
user-select: none; | ||
-webkit-user-select: none; | ||
vertical-align: top; | ||
white-space: nowrap; | ||
width: 25%; | ||
z-index: 9; | ||
border: 0; | ||
transition: box-shadow .2s; | ||
margin-top: 5px; | ||
} | ||
|
||
.submit-button:hover { | ||
box-shadow: rgba(253, 76, 0, 0.5) 0 3px 25px; | ||
} | ||
|
||
.image-gallery { | ||
width: 90%; | ||
height: auto; | ||
} |
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,168 @@ | ||
import "./TargetMatch.css" | ||
|
||
import { useState } from "react"; | ||
import { AirdropTarget, GPSCoord} from '../protos/obc.pb'; | ||
import { useMyModal } from "../components/UseMyModal"; | ||
|
||
import MyModal from "../components/MyModal"; | ||
|
||
/** | ||
* @returns Returns manual target matching page. | ||
*/ | ||
function TargetMatch() { | ||
|
||
const {modalVisible, openModal, closeModal} = useMyModal(); | ||
const [modalType, setModalType] = useState('default'); | ||
const [modalMessage, setModalMessage] = useState(''); | ||
const [modalLoading, setModalLoading] = useState(true); | ||
/** | ||
* The bottles that exist. | ||
*/ | ||
const bottle_list = ['A', 'B', 'C', 'D', 'E']; | ||
|
||
/** | ||
* Define the initial state for lat_lng | ||
*/ | ||
const lat_lng_template = [ | ||
{ lat: '', lng: '', setLat: (value: number|string) => handleUpdate(0, 'lat', value), setLng: (value: number|string) => handleUpdate(0, 'lng', value) }, | ||
{ lat: '', lng: '', setLat: (value: number|string) => handleUpdate(1, 'lat', value), setLng: (value: number|string) => handleUpdate(1, 'lng', value) }, | ||
{ lat: '', lng: '', setLat: (value: number|string) => handleUpdate(2, 'lat', value), setLng: (value: number|string) => handleUpdate(2, 'lng', value) }, | ||
{ lat: '', lng: '', setLat: (value: number|string) => handleUpdate(3, 'lat', value), setLng: (value: number|string) => handleUpdate(3, 'lng', value) }, | ||
{ lat: '', lng: '', setLat: (value: number|string) => handleUpdate(4, 'lat', value), setLng: (value: number|string) => handleUpdate(4, 'lng', value) } | ||
]; | ||
|
||
/** | ||
* A state variable that is an array where each element is a json object that | ||
* contains the latitude, longitude, latitude setter, and longitude setter. | ||
* It has 5 json because there are five bottles. | ||
*/ | ||
const [lat_lng, set_lat_lng] = useState(lat_lng_template); | ||
|
||
/** | ||
* This function handels the set_lat_lng state setter. Since lat_lng | ||
* is an array, to change a specific value, we use this function to index | ||
* into it. | ||
* @param index The index that help you grab the specific json. | ||
* @param key This either 'lat' or 'lng'. | ||
* @param value The number representing the latitude or longitude. | ||
*/ | ||
const handleUpdate = (index:number, key:string, value:number|string) => { | ||
set_lat_lng(pre_lat_lng => { | ||
const new_lat_lng = [...pre_lat_lng]; | ||
new_lat_lng[index] = { ...new_lat_lng[index], [key]: value }; | ||
return new_lat_lng; | ||
}); | ||
}; | ||
|
||
|
||
/** | ||
* This functions puts all the values in the lat_lng variable into an array | ||
* consisting of the struct AirdropTarget from obc.protos. | ||
* @param event A form tag event. | ||
* | ||
* [ | ||
* { | ||
* Index: BottleDropIndex, | ||
* Coordiante: GPSCoord, | ||
* }, | ||
* ... | ||
* ] | ||
*/ | ||
const handleSubmit = (event: React.FormEvent<HTMLFormElement>) => { | ||
event.preventDefault(); | ||
setModalLoading(true); | ||
const airdrop_target_list: AirdropTarget[] = []; | ||
bottle_list.forEach((_, index: number) => { | ||
if(lat_lng[index].lat != '' && lat_lng[index].lng != '') { | ||
const coordiante: GPSCoord = { | ||
Latitude: parseInt(lat_lng[index].lat), | ||
Longitude: parseInt(lat_lng[index].lng), | ||
Altitude: 0, | ||
} | ||
const airdrop_target: AirdropTarget = { | ||
Index: index+1, | ||
Coordinate: coordiante, | ||
} | ||
airdrop_target_list.push(airdrop_target); | ||
} | ||
|
||
}); | ||
set_lat_lng(lat_lng_template); | ||
|
||
if(airdrop_target_list.length > 0) { | ||
fetch("/api/airdrop", { | ||
method: "POST", | ||
headers: { | ||
"Content-Type": "application/json" | ||
}, | ||
body: JSON.stringify(airdrop_target_list) | ||
}) | ||
.then(response => { | ||
if (response.status == 200) { | ||
return response.text() | ||
} else { | ||
throw response.text(); | ||
} | ||
}) | ||
.then(data => { | ||
setModalType('default'); | ||
setModalMessage(data) | ||
}) | ||
.catch(err => { | ||
console.log("ERROR: " + err); | ||
setModalType('error'); | ||
setModalMessage(err.toString()); | ||
}) | ||
} else { | ||
setModalType('warning'); | ||
setModalMessage('Form is empty or imcomplete'); | ||
} | ||
setModalLoading(false); | ||
}; | ||
|
||
|
||
return ( | ||
<div className="flex-box"> | ||
<div className="form-container"> | ||
<form onSubmit={(e) => handleSubmit(e)} > | ||
{ | ||
bottle_list.map((bottle, index) => { | ||
return ( | ||
<div className="bottle" key={index}> | ||
<div style={{fontSize:'50px', fontWeight:'bold'}}>Bottle {bottle}</div> | ||
<input className="input-field" type="number" placeholder="lat" value={lat_lng[index].lat} onChange={(e) => { | ||
const value = e.target.value; | ||
if (value.trim() === '') { | ||
lat_lng[index].setLat(''); | ||
} else { | ||
const numericValue = parseInt(value); | ||
if (!isNaN(numericValue)) { | ||
lat_lng[index].setLat(numericValue); | ||
} | ||
} | ||
}} /> | ||
<input className="input-field" type="number" placeholder="lng" value={lat_lng[index].lng} onChange={(e) => { | ||
const value = e.target.value; | ||
if (value.trim() === '') { | ||
lat_lng[index].setLng(''); | ||
} else { | ||
const numericValue = parseInt(value); | ||
if (!isNaN(numericValue)) { | ||
lat_lng[index].setLng(numericValue); | ||
} | ||
} | ||
}} /> | ||
</div> | ||
) | ||
}) | ||
} | ||
<input className="submit-button" type="submit" value="Submit" onClick={openModal}></input> | ||
</form> | ||
</div> | ||
<MyModal modalVisible={modalVisible} closeModal={closeModal} type={modalType} loading={modalLoading}> | ||
{modalMessage} | ||
</MyModal> | ||
</div> | ||
) | ||
} | ||
export default TargetMatch; |
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