added delete functionality and updated button styles
This commit is contained in:
@@ -130,7 +130,7 @@ const CameraSettingFields = ({
|
|||||||
|
|
||||||
<button
|
<button
|
||||||
type="submit"
|
type="submit"
|
||||||
className="bg-blue-800 text-white rounded-lg p-2 mx-auto h-[100%] w-full"
|
className="bg-[#26B170] text-white rounded-lg p-2 mx-auto h-[100%] w-full"
|
||||||
>
|
>
|
||||||
Save settings
|
Save settings
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
@@ -4,6 +4,10 @@ import SightingModal from "../SightingModal/SightingModal";
|
|||||||
import InfoBar from "../SightingsWidget/InfoBar";
|
import InfoBar from "../SightingsWidget/InfoBar";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import HotListImg from "/Hotlist_Hit.svg";
|
import HotListImg from "/Hotlist_Hit.svg";
|
||||||
|
import { useAlertHitContext } from "../../context/AlertHitContext";
|
||||||
|
import NPED_CAT_A from "/NPED_Cat_A.svg";
|
||||||
|
import NPED_CAT_B from "/NPED_Cat_B.svg";
|
||||||
|
import NPED_CAT_C from "/NPED_Cat_C.svg";
|
||||||
|
|
||||||
type AlertItemProps = {
|
type AlertItemProps = {
|
||||||
item: SightingType;
|
item: SightingType;
|
||||||
@@ -11,8 +15,12 @@ type AlertItemProps = {
|
|||||||
|
|
||||||
const AlertItem = ({ item }: AlertItemProps) => {
|
const AlertItem = ({ item }: AlertItemProps) => {
|
||||||
const [isModalOpen, setIsModalOpen] = useState(false);
|
const [isModalOpen, setIsModalOpen] = useState(false);
|
||||||
|
const { dispatch } = useAlertHitContext();
|
||||||
const motionAway = (item?.motion ?? "").toUpperCase() === "AWAY";
|
const motionAway = (item?.motion ?? "").toUpperCase() === "AWAY";
|
||||||
const isHotListHit = item?.metadata?.hotlistMatches?.Hotlist0 === true;
|
const isHotListHit = item?.metadata?.hotlistMatches?.Hotlist0 === true;
|
||||||
|
const isNPEDHitA = item?.metadata?.npedJSON?.["NPED CATEGORY"] === "A";
|
||||||
|
const isNPEDHitB = item?.metadata?.npedJSON?.["NPED CATEGORY"] === "B";
|
||||||
|
const isNPEDHitC = item?.metadata?.npedJSON?.["NPED CATEGORY"] === "C";
|
||||||
|
|
||||||
const handleClick = () => {
|
const handleClick = () => {
|
||||||
setIsModalOpen(true);
|
setIsModalOpen(true);
|
||||||
@@ -21,11 +29,16 @@ const AlertItem = ({ item }: AlertItemProps) => {
|
|||||||
const closeModal = () => {
|
const closeModal = () => {
|
||||||
setIsModalOpen(false);
|
setIsModalOpen(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleDelete = () => {
|
||||||
|
dispatch({ type: "REMOVE", payload: item });
|
||||||
|
};
|
||||||
return (
|
return (
|
||||||
<>
|
<div className="flex flex-col w-full">
|
||||||
|
<div className="border border-gray-400 rounded-lg items-center py-1">
|
||||||
<InfoBar obj={item} />
|
<InfoBar obj={item} />
|
||||||
<div
|
<div
|
||||||
className=" flex flex-row p-4 border border-gray-400 rounded-lg items-center w-full mx-auto justify-between"
|
className=" flex flex-row p-4 w-full mx-auto justify-between"
|
||||||
onClick={handleClick}
|
onClick={handleClick}
|
||||||
>
|
>
|
||||||
{isHotListHit && (
|
{isHotListHit && (
|
||||||
@@ -35,6 +48,27 @@ const AlertItem = ({ item }: AlertItemProps) => {
|
|||||||
className="h-20 object-contain rounded-md"
|
className="h-20 object-contain rounded-md"
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
{isNPEDHitA && (
|
||||||
|
<img
|
||||||
|
src={NPED_CAT_A}
|
||||||
|
alt="hotlistHit"
|
||||||
|
className="h-20 object-contain rounded-md"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{isNPEDHitB && (
|
||||||
|
<img
|
||||||
|
src={NPED_CAT_B}
|
||||||
|
alt="hotlistHit"
|
||||||
|
className="h-20 object-contain rounded-md"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{isNPEDHitC && (
|
||||||
|
<img
|
||||||
|
src={NPED_CAT_C}
|
||||||
|
alt="hotlistHit"
|
||||||
|
className="h-20 object-contain rounded-md"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
<div className="flex flex-col">
|
<div className="flex flex-col">
|
||||||
<small>MAKE: {item.make}</small>
|
<small>MAKE: {item.make}</small>
|
||||||
@@ -48,8 +82,10 @@ const AlertItem = ({ item }: AlertItemProps) => {
|
|||||||
isSightingModalOpen={isModalOpen}
|
isSightingModalOpen={isModalOpen}
|
||||||
handleClose={closeModal}
|
handleClose={closeModal}
|
||||||
sighting={item}
|
sighting={item}
|
||||||
|
onDelete={handleDelete}
|
||||||
/>
|
/>
|
||||||
</>
|
</div>
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,18 +1,30 @@
|
|||||||
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||||
import { useAlertHitContext } from "../../context/AlertHitContext";
|
import { useAlertHitContext } from "../../context/AlertHitContext";
|
||||||
|
import type { SightingType } from "../../types/types";
|
||||||
import Card from "../UI/Card";
|
import Card from "../UI/Card";
|
||||||
import CardHeader from "../UI/CardHeader";
|
import CardHeader from "../UI/CardHeader";
|
||||||
import AlertItem from "./AlertItem";
|
import AlertItem from "./AlertItem";
|
||||||
|
import { faTrash } from "@fortawesome/free-solid-svg-icons";
|
||||||
|
|
||||||
const HistoryList = () => {
|
const HistoryList = () => {
|
||||||
const { state } = useAlertHitContext();
|
const { state, dispatch } = useAlertHitContext();
|
||||||
|
|
||||||
|
const handleDeleteClick = (alertItem: SightingType) =>
|
||||||
|
dispatch({ type: "REMOVE", payload: alertItem });
|
||||||
return (
|
return (
|
||||||
<Card className="h-100">
|
<Card className="h-100">
|
||||||
<CardHeader title="Alert History" />
|
<CardHeader title="Alert History" />
|
||||||
<div className="flex flex-col gap-1">
|
<div className="flex flex-col gap-1">
|
||||||
{state?.alertList?.length > 0 ? (
|
{state?.alertList?.length > 0 ? (
|
||||||
state?.alertList?.map((alertItem, index) => (
|
state?.alertList?.map((alertItem, index) => (
|
||||||
<AlertItem key={index} item={alertItem} />
|
<div key={index} className="flex flex-row space-x-2">
|
||||||
|
<AlertItem item={alertItem} />
|
||||||
|
<button onClick={() => handleDeleteClick(alertItem)}>
|
||||||
|
<div className="p-4">
|
||||||
|
<FontAwesomeIcon icon={faTrash} size="2x" />
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
))
|
))
|
||||||
) : (
|
) : (
|
||||||
<p>No Alert results</p>
|
<p>No Alert results</p>
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ const SessionCard = () => {
|
|||||||
</div>
|
</div>
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
<button
|
<button
|
||||||
className="bg-[#26B170] text-white px-4 py-2 rounded hover:bg-green-700 transition w-full max-w-md"
|
className="bg-[#26B170] text-white px-4 py-2 rounded hover:bg-green-700 transition w-full mx-auto"
|
||||||
onClick={() => dispatch({ type: "SEARCH", payload: searchTerm })}
|
onClick={() => dispatch({ type: "SEARCH", payload: searchTerm })}
|
||||||
disabled={searchTerm.trim().length < 2}
|
disabled={searchTerm.trim().length < 2}
|
||||||
>
|
>
|
||||||
@@ -40,7 +40,7 @@ const SessionCard = () => {
|
|||||||
</button>
|
</button>
|
||||||
{searchTerm && (
|
{searchTerm && (
|
||||||
<button
|
<button
|
||||||
className="bg-gray-300 text-gray-900 px-4 py-2 rounded hover:bg-gray-700 transition w-full max-w-md"
|
className="bg-gray-300 text-gray-900 px-4 py-2 rounded hover:bg-gray-700 transition w-full mx-auto"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setSearchTerm("");
|
setSearchTerm("");
|
||||||
dispatch({ type: "SEARCH", payload: "" });
|
dispatch({ type: "SEARCH", payload: "" });
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ const SessionCard = () => {
|
|||||||
<CardHeader title="Session" />
|
<CardHeader title="Session" />
|
||||||
<div className="flex flex-col gap-4">
|
<div className="flex flex-col gap-4">
|
||||||
<button
|
<button
|
||||||
className="bg-[#26B170] text-white px-4 py-2 rounded hover:bg-green-700 transition w-full max-w-md"
|
className="bg-[#26B170] text-white px-4 py-2 rounded hover:bg-green-700 transition w-full"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
play();
|
play();
|
||||||
}}
|
}}
|
||||||
|
|||||||
@@ -72,9 +72,9 @@ const SettingForms = () => {
|
|||||||
)}
|
)}
|
||||||
<button
|
<button
|
||||||
type="submit"
|
type="submit"
|
||||||
className="w-1/4 text-white bg-blue-700 hover:bg-blue-800 font-small rounded-lg text-sm px-2 py-2.5"
|
className="bg-[#26B170] text-white px-4 py-2 rounded hover:bg-green-700 transition w-full md:w-[50%]"
|
||||||
>
|
>
|
||||||
Save changes
|
Save Changes
|
||||||
</button>
|
</button>
|
||||||
</Form>
|
</Form>
|
||||||
</Formik>
|
</Formik>
|
||||||
|
|||||||
@@ -130,7 +130,7 @@ const SystemConfigFields = () => {
|
|||||||
</FormGroup>
|
</FormGroup>
|
||||||
<button
|
<button
|
||||||
type="submit"
|
type="submit"
|
||||||
className="bg-[#26B170] text-white px-4 py-2 rounded hover:bg-green-700 transition w-full max-w-md"
|
className="bg-[#26B170] text-white px-4 py-2 rounded hover:bg-green-700 transition w-full md:w-[50%]"
|
||||||
>
|
>
|
||||||
Save System Settings
|
Save System Settings
|
||||||
</button>
|
</button>
|
||||||
@@ -144,14 +144,14 @@ const SystemConfigFields = () => {
|
|||||||
|
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="bg-red-600 text-white px-4 py-2 rounded hover:bg-red-700 transition w-full max-w-md"
|
className="bg-red-600 text-white px-4 py-2 rounded hover:bg-red-700 transition w-full md:w-[50%]"
|
||||||
onClick={handleSoftReboot}
|
onClick={handleSoftReboot}
|
||||||
>
|
>
|
||||||
Software Reboot
|
Software Reboot
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="bg-red-600 text-white px-4 py-2 rounded hover:bg-red-700 transition w-full max-w-md"
|
className="bg-red-600 text-white px-4 py-2 rounded hover:bg-red-700 transition w-full md:w-[50%]"
|
||||||
onClick={handleHardReboot}
|
onClick={handleHardReboot}
|
||||||
>
|
>
|
||||||
Hardware Reboot
|
Hardware Reboot
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ const SystemFileUpload = ({ name, selectedFile }: SystemFileUploadProps) => {
|
|||||||
</FormGroup>
|
</FormGroup>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="w-full max-w-md text-white bg-[#26B170] hover:bg-green-700 font-small rounded-lg text-sm px-2 py-2.5 disabled:opacity-50 disabled:cursor-not-allowed"
|
className="w-full md:w-[50%] text-white bg-[#26B170] hover:bg-green-700 font-small rounded-lg text-sm px-2 py-2.5 disabled:opacity-50 disabled:cursor-not-allowed"
|
||||||
disabled={!selectedFile}
|
disabled={!selectedFile}
|
||||||
onClick={handleFileUploadClick}
|
onClick={handleFileUploadClick}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ const ModemCard = () => {
|
|||||||
</select>
|
</select>
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
<button
|
<button
|
||||||
className="bg-[#26B170] text-white px-4 py-2 rounded hover:bg-green-700 transition w-full max-w-md"
|
className="bg-[#26B170] text-white px-4 py-2 rounded hover:bg-green-700 transition w-full md:w-[50%]"
|
||||||
//onClick={() => handleModemSave(apn, username, password, authType)}
|
//onClick={() => handleModemSave(apn, username, password, authType)}
|
||||||
>
|
>
|
||||||
Save Modem Settings
|
Save Modem Settings
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ const WiFiCard = () => {
|
|||||||
</select>
|
</select>
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
<button
|
<button
|
||||||
className="bg-[#26B170] text-white px-4 py-2 rounded hover:bg-green-700 transition w-full max-w-md"
|
className="bg-[#26B170] text-white px-4 py-2 rounded hover:bg-green-700 transition w-full md:w-[50%]"
|
||||||
//onClick={() => handleWiFiSave(ssid, password, encryption)}
|
//onClick={() => handleWiFiSave(ssid, password, encryption)}
|
||||||
>
|
>
|
||||||
Save WiFi Settings
|
Save WiFi Settings
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { faCheck, faX } from "@fortawesome/free-solid-svg-icons";
|
import { faCheck, faTrash, faX } from "@fortawesome/free-solid-svg-icons";
|
||||||
import type { SightingType } from "../../types/types";
|
import type { SightingType } from "../../types/types";
|
||||||
import NumberPlate from "../PlateStack/NumberPlate";
|
import NumberPlate from "../PlateStack/NumberPlate";
|
||||||
import ModalComponent from "../UI/ModalComponent";
|
import ModalComponent from "../UI/ModalComponent";
|
||||||
@@ -14,12 +14,14 @@ type SightingModalProps = {
|
|||||||
isSightingModalOpen: boolean;
|
isSightingModalOpen: boolean;
|
||||||
handleClose: () => void;
|
handleClose: () => void;
|
||||||
sighting: SightingType | null;
|
sighting: SightingType | null;
|
||||||
|
onDelete?: () => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
const SightingModal = ({
|
const SightingModal = ({
|
||||||
isSightingModalOpen,
|
isSightingModalOpen,
|
||||||
handleClose,
|
handleClose,
|
||||||
sighting,
|
sighting,
|
||||||
|
onDelete,
|
||||||
}: SightingModalProps) => {
|
}: SightingModalProps) => {
|
||||||
const { dispatch } = useAlertHitContext();
|
const { dispatch } = useAlertHitContext();
|
||||||
|
|
||||||
@@ -34,6 +36,13 @@ const SightingModal = ({
|
|||||||
handleClose();
|
handleClose();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleDeleteClick = () => {
|
||||||
|
if (!onDelete) return;
|
||||||
|
onDelete();
|
||||||
|
handleClose();
|
||||||
|
toast.success("Sighting removed from alert list");
|
||||||
|
};
|
||||||
|
|
||||||
const motionAway = (sighting?.motion ?? "").toUpperCase() === "AWAY";
|
const motionAway = (sighting?.motion ?? "").toUpperCase() === "AWAY";
|
||||||
const isHotListHit = sighting?.metadata?.hotlistMatches?.Hotlist0 === true;
|
const isHotListHit = sighting?.metadata?.hotlistMatches?.Hotlist0 === true;
|
||||||
const isNPEDHitA = sighting?.metadata?.npedJSON?.["NPED CATEGORY"] === "A";
|
const isNPEDHitA = sighting?.metadata?.npedJSON?.["NPED CATEGORY"] === "A";
|
||||||
@@ -147,6 +156,15 @@ const SightingModal = ({
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="mt-3 flex flex-col-reverse gap-3 md:flex-row md:justify-center">
|
<div className="mt-3 flex flex-col-reverse gap-3 md:flex-row md:justify-center">
|
||||||
|
{onDelete ? (
|
||||||
|
<button
|
||||||
|
className="inline-flex items-center justify-center gap-2 rounded-lg px-5 py-3 bg-blue-600 text-white hover:bg-blue-700 w-full md:w-full"
|
||||||
|
onClick={handleClose}
|
||||||
|
>
|
||||||
|
<FontAwesomeIcon icon={faX} />
|
||||||
|
Close
|
||||||
|
</button>
|
||||||
|
) : (
|
||||||
<button
|
<button
|
||||||
className="inline-flex items-center justify-center gap-2 rounded-lg px-5 py-3 bg-green-600 text-white hover:bg-green-700 w-full md:w-full"
|
className="inline-flex items-center justify-center gap-2 rounded-lg px-5 py-3 bg-green-600 text-white hover:bg-green-700 w-full md:w-full"
|
||||||
onClick={handleAcknowledgeButton}
|
onClick={handleAcknowledgeButton}
|
||||||
@@ -154,6 +172,16 @@ const SightingModal = ({
|
|||||||
<FontAwesomeIcon icon={faCheck} />
|
<FontAwesomeIcon icon={faCheck} />
|
||||||
Accept
|
Accept
|
||||||
</button>
|
</button>
|
||||||
|
)}
|
||||||
|
{onDelete ? (
|
||||||
|
<button
|
||||||
|
className="inline-flex items-center justify-center gap-2 rounded-lg px-5 py-3 bg-red-600 text-white hover:bg-red-700 w-full md:w-full"
|
||||||
|
onClick={handleDeleteClick}
|
||||||
|
>
|
||||||
|
<FontAwesomeIcon icon={faTrash} />
|
||||||
|
Delete
|
||||||
|
</button>
|
||||||
|
) : (
|
||||||
<button
|
<button
|
||||||
className="inline-flex items-center justify-center gap-2 rounded-lg px-5 py-3 bg-red-600 text-white hover:bg-red-700 w-full md:w-full"
|
className="inline-flex items-center justify-center gap-2 rounded-lg px-5 py-3 bg-red-600 text-white hover:bg-red-700 w-full md:w-full"
|
||||||
onClick={handleClose}
|
onClick={handleClose}
|
||||||
@@ -161,6 +189,7 @@ const SightingModal = ({
|
|||||||
<FontAwesomeIcon icon={faX} />
|
<FontAwesomeIcon icon={faX} />
|
||||||
Deny
|
Deny
|
||||||
</button>
|
</button>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</ModalComponent>
|
</ModalComponent>
|
||||||
|
|||||||
@@ -97,7 +97,7 @@ export default function Header() {
|
|||||||
<img src={Logo} alt="Logo" width={150} height={150} />
|
<img src={Logo} alt="Logo" width={150} height={150} />
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-col md:flex-row items-center space-x-24 justify-items-center">
|
<div className="flex flex-col lg:flex-row items-center space-x-24 justify-items-center">
|
||||||
<div className="flex flex-col leading-tight text-white tabular-nums text-xl text-right mx-auto md:mx-10 space-y-1 my-2">
|
<div className="flex flex-col leading-tight text-white tabular-nums text-xl text-right mx-auto md:mx-10 space-y-1 my-2">
|
||||||
<h2>Local: {localStr}</h2>
|
<h2>Local: {localStr}</h2>
|
||||||
<h2>UTC: {utcStr}</h2>
|
<h2>UTC: {utcStr}</h2>
|
||||||
@@ -113,7 +113,7 @@ export default function Header() {
|
|||||||
<div onClick={refreshBrowser}>
|
<div onClick={refreshBrowser}>
|
||||||
<FontAwesomeIcon icon={faRotate} size="2x" />
|
<FontAwesomeIcon icon={faRotate} size="2x" />
|
||||||
</div>
|
</div>
|
||||||
|
<SoundBtn />
|
||||||
<Link to={"/session-settings"}>
|
<Link to={"/session-settings"}>
|
||||||
<FontAwesomeIcon
|
<FontAwesomeIcon
|
||||||
className="text-white"
|
className="text-white"
|
||||||
@@ -121,7 +121,7 @@ export default function Header() {
|
|||||||
size="2x"
|
size="2x"
|
||||||
/>
|
/>
|
||||||
</Link>
|
</Link>
|
||||||
<SoundBtn />
|
|
||||||
<Link to={"/system-settings"}>
|
<Link to={"/system-settings"}>
|
||||||
<FontAwesomeIcon className="text-white" icon={faGear} size="2x" />
|
<FontAwesomeIcon className="text-white" icon={faGear} size="2x" />
|
||||||
</Link>
|
</Link>
|
||||||
|
|||||||
@@ -41,6 +41,15 @@ export function reducer(state: AlertState, action: AlertPayload) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case "REMOVE": {
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
alertList: state.alertList.filter(
|
||||||
|
(alertItem) => alertItem.vrm !== action.payload.vrm
|
||||||
|
),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return { ...state };
|
return { ...state };
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,13 +6,13 @@ import { CAM_BASE } from "../utils/config";
|
|||||||
|
|
||||||
const Dashboard = () => {
|
const Dashboard = () => {
|
||||||
const dev_REAR_URL = `${CAM_BASE}/SightingListRear/sightingSummary?mostRecentRef=`;
|
const dev_REAR_URL = `${CAM_BASE}/SightingListRear/sightingSummary?mostRecentRef=`;
|
||||||
const dev_FRONT_URL = `${CAM_BASE}/SightingListFront/sightingSummary?mostRecentRef=`;
|
// const dev_FRONT_URL = `${CAM_BASE}/SightingListFront/sightingSummary?mostRecentRef=`;
|
||||||
|
const folkURL = import.meta.env.VITE_FOLKESTONE_URL;
|
||||||
console.log(CAM_BASE);
|
console.log(CAM_BASE);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="mx-auto grid grid-cols-1 sm:grid-cols-1 lg:grid-cols-2 gap-2 px-1 sm:px-2 lg:px-0 w-full">
|
<div className="mx-auto grid grid-cols-1 sm:grid-cols-1 lg:grid-cols-2 gap-2 px-1 sm:px-2 lg:px-0 w-full">
|
||||||
<SightingFeedProvider url={dev_FRONT_URL} side="Front">
|
<SightingFeedProvider url={folkURL} side="Front">
|
||||||
<FrontCameraOverviewCard className="order-1" />
|
<FrontCameraOverviewCard className="order-1" />
|
||||||
<SightingHistoryWidget
|
<SightingHistoryWidget
|
||||||
className="order-3"
|
className="order-3"
|
||||||
|
|||||||
@@ -160,6 +160,10 @@ export type AlertPayload =
|
|||||||
| {
|
| {
|
||||||
payload: string;
|
payload: string;
|
||||||
type: "SEARCH";
|
type: "SEARCH";
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
type: "REMOVE";
|
||||||
|
payload: SightingType;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type ActionType = {
|
export type ActionType = {
|
||||||
|
|||||||
Reference in New Issue
Block a user