mirror of
https://github.com/BZmHackTeam/BezpiecznaZywnosc
synced 2024-12-22 14:46:58 +01:00
Prototype release
This commit is contained in:
parent
cee83f1894
commit
28173f16e8
6 changed files with 278 additions and 32 deletions
|
@ -0,0 +1,3 @@
|
|||
.addWarningButton {
|
||||
width: 100%;
|
||||
}
|
|
@ -0,0 +1,135 @@
|
|||
import { IonButton, IonContent, IonHeader, IonInput, IonItem, IonLabel, IonModal, IonPage, IonTitle, IonToolbar } from "@ionic/react";
|
||||
|
||||
import styles from "./AddWarningButton.module.css";
|
||||
|
||||
import { FormEventHandler, useState } from "react";
|
||||
|
||||
const AddWarningButton: React.FC = () => {
|
||||
const [shouldOpenModal, setShouldOpenModal] = useState(false);
|
||||
|
||||
function openModal() {
|
||||
setShouldOpenModal(true);
|
||||
};
|
||||
|
||||
const [formData, setFormData] = useState({
|
||||
name: '',
|
||||
productName: '',
|
||||
producer: '',
|
||||
submitterAddress: '',
|
||||
description: '',
|
||||
location: ''
|
||||
});
|
||||
|
||||
const handleSubmit: FormEventHandler<HTMLFormElement> = async (e) => {
|
||||
e.preventDefault();
|
||||
|
||||
try {
|
||||
const response = await fetch('/api/incident/submit', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(formData),
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
console.log('Form submitted successfully.');
|
||||
} else {
|
||||
console.error('Form submission failed.');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error:', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
const handleInputChange = (fieldName: any, value: any) => {
|
||||
setFormData({
|
||||
...formData,
|
||||
[fieldName]: value,
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<IonButton onClick={openModal} className={styles.addWarningButton} color="success">
|
||||
Wyślij własne zgłoszenie
|
||||
</IonButton>
|
||||
<IonModal isOpen={shouldOpenModal}>
|
||||
<IonPage>
|
||||
<IonHeader>
|
||||
<IonToolbar>
|
||||
<IonTitle>
|
||||
Zgłoszenie
|
||||
</IonTitle>
|
||||
</IonToolbar>
|
||||
</IonHeader>
|
||||
<IonContent fullscreen>
|
||||
<IonHeader collapse="condense">
|
||||
<IonToolbar>
|
||||
<IonTitle size="large">
|
||||
Zgłoszenie
|
||||
</IonTitle>
|
||||
</IonToolbar>
|
||||
</IonHeader>
|
||||
<form onSubmit={handleSubmit}>
|
||||
<IonItem>
|
||||
<IonLabel position="floating">Imię</IonLabel>
|
||||
<IonInput
|
||||
type="text"
|
||||
value={formData.name}
|
||||
onIonChange={(e) => handleInputChange('name', e.detail.value)}
|
||||
/>
|
||||
</IonItem>
|
||||
<IonItem>
|
||||
<IonLabel position="floating">Nazwa produktu</IonLabel>
|
||||
<IonInput
|
||||
type="text"
|
||||
value={formData.productName}
|
||||
onIonChange={(e) => handleInputChange('productName', e.detail.value)}
|
||||
/>
|
||||
</IonItem>
|
||||
<IonItem>
|
||||
<IonLabel position="floating">Producent</IonLabel>
|
||||
<IonInput
|
||||
type="text"
|
||||
value={formData.producer}
|
||||
onIonChange={(e) => handleInputChange('producer', e.detail.value)}
|
||||
/>
|
||||
</IonItem>
|
||||
<IonItem>
|
||||
<IonLabel position="floating">Lokalizacja</IonLabel>
|
||||
<IonInput
|
||||
type="text"
|
||||
value={formData.location}
|
||||
onIonChange={(e) => handleInputChange('location', e.detail.value)}
|
||||
/>
|
||||
</IonItem>
|
||||
<IonItem>
|
||||
<IonLabel position="floating">Opis</IonLabel>
|
||||
<IonInput
|
||||
type="text"
|
||||
value={formData.description}
|
||||
onIonChange={(e) => handleInputChange('description', e.detail.value)}
|
||||
/>
|
||||
</IonItem>
|
||||
<IonItem>
|
||||
<IonLabel position="floating">Adres e-mail</IonLabel>
|
||||
<IonInput
|
||||
type="text"
|
||||
value={formData.submitterAddress}
|
||||
onIonChange={(e) => handleInputChange('submitterAddress', e.detail.value)}
|
||||
/>
|
||||
</IonItem>
|
||||
<IonButton expand="full" type="submit">
|
||||
Wyślij
|
||||
</IonButton>
|
||||
</form>
|
||||
</IonContent>
|
||||
</IonPage>
|
||||
</IonModal>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default AddWarningButton;
|
|
@ -1,11 +1,16 @@
|
|||
import { IonItem, IonLabel, IonList } from "@ionic/react";
|
||||
import { IonBackButton, IonButton, IonButtons, IonContent, IonHeader, IonInfiniteScroll, IonInfiniteScrollContent, IonItem, IonLabel, IonList, IonModal, IonTitle, IonToolbar } from "@ionic/react";
|
||||
|
||||
import { useEffect, useState } from "react";
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
|
||||
const WarningsList: React.FC = () => {
|
||||
const [dataset, setDataset] = useState<any[]>([]);
|
||||
const [warningsIds, setWarningsIds] = useState<string[]>([]);
|
||||
const [warningsContent, setWarningsContent] = useState<any[]>([]);
|
||||
const [shouldFetchMoreData, setShouldFetchMoreData] = useState(false);
|
||||
const [isFirstRequest, setIsFirstRequest] = useState(true);
|
||||
const [pageIndex, setPageIndex] = useState(1);
|
||||
const [isModalOpen, setIsModalOpen] = useState(false);
|
||||
const [currentlySelectedWarning, setCurrentlySelectedWarning] = useState<object>();
|
||||
const eventRef = useRef();
|
||||
|
||||
useEffect(() => {
|
||||
async function getDataset() {
|
||||
|
@ -13,50 +18,143 @@ const WarningsList: React.FC = () => {
|
|||
const data = await response.json();
|
||||
|
||||
setDataset(data.data);
|
||||
console.log(data.data);
|
||||
};
|
||||
|
||||
getDataset();
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (dataset !== null && dataset !== undefined) {
|
||||
const datasetLength = (dataset as any).length;
|
||||
|
||||
for (let i = 0; i < datasetLength; i++) {
|
||||
setWarningsIds(previousWarningsIds => [...previousWarningsIds, (dataset as any)[i].id]);
|
||||
}
|
||||
}
|
||||
}, [dataset]);
|
||||
|
||||
useEffect(() => {
|
||||
if (warningsIds.length === 20) {
|
||||
async function getWarningsContent(id: string) {
|
||||
const response = await fetch(`https://api.dane.gov.pl/1.4/resources/${id}/data?page=1&per_page=20`);
|
||||
if (dataset !== undefined && dataset !== null) {
|
||||
if (isFirstRequest === true) {
|
||||
async function getDatasetElements() {
|
||||
for (let datasetElement of dataset) {
|
||||
const response = await fetch(datasetElement.relationships.tabular_data.links.related);
|
||||
const data = await response.json();
|
||||
|
||||
setWarningsContent(previousWarningsContent => [...previousWarningsContent, data.data[0].attributes]);
|
||||
};
|
||||
|
||||
for (let i = 0; i < warningsIds.length; i++) {
|
||||
getWarningsContent(warningsIds[i]);
|
||||
};
|
||||
|
||||
console.log("First content request");
|
||||
getDatasetElements();
|
||||
}
|
||||
}, [warningsIds]);
|
||||
};
|
||||
}, [dataset]);
|
||||
|
||||
useEffect(() => {
|
||||
if (warningsContent.length === 20) {
|
||||
setIsFirstRequest(false);
|
||||
};
|
||||
}, [warningsContent]);
|
||||
|
||||
function onIonScroll(event: any) {
|
||||
setPageIndex(previousPageIndex => previousPageIndex + 1);
|
||||
setShouldFetchMoreData(true);
|
||||
eventRef.current = event;
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (shouldFetchMoreData) {
|
||||
async function fetchNewData() {
|
||||
const response = await fetch(`https://api.dane.gov.pl/1.4/datasets/855/resources?page=${pageIndex}&per_page=20&sort=-data_date&include=institution`);
|
||||
const data = await response.json();
|
||||
|
||||
setDataset(previousDataset => [...previousDataset, ...data.data]);
|
||||
|
||||
for (let dataElement of data.data) {
|
||||
const response2 = await fetch(dataElement.relationships.tabular_data.links.related);
|
||||
const data2 = await response2.json();
|
||||
|
||||
setWarningsContent(previousWarningsContent => [...previousWarningsContent, data2.data[0].attributes]);
|
||||
};
|
||||
|
||||
let id = setTimeout(() => {
|
||||
setShouldFetchMoreData(false);
|
||||
(eventRef.current as any).target.complete();
|
||||
}, 5000);
|
||||
|
||||
return () => {
|
||||
clearTimeout(id);
|
||||
};
|
||||
}
|
||||
|
||||
fetchNewData();
|
||||
}
|
||||
}, [shouldFetchMoreData]);
|
||||
|
||||
function openModal(warningContent: any) {
|
||||
setCurrentlySelectedWarning(warningContent);
|
||||
console.log(warningContent);
|
||||
setIsModalOpen(true);
|
||||
};
|
||||
|
||||
return warningsContent.length > 0 ? (
|
||||
<>
|
||||
<>
|
||||
<IonList lines="full">
|
||||
{warningsContent.map((warningContent, key) => (
|
||||
<IonItem key={key}>
|
||||
<IonItem onClick={() => openModal(warningContent)} button key={key}>
|
||||
<IonLabel>
|
||||
{warningContent.col7.val}
|
||||
</IonLabel>
|
||||
</IonItem>
|
||||
))}
|
||||
</IonList>
|
||||
<IonModal isOpen={isModalOpen}>
|
||||
<IonHeader>
|
||||
<IonToolbar>
|
||||
<IonTitle>
|
||||
Szczegóły
|
||||
</IonTitle>
|
||||
</IonToolbar>
|
||||
</IonHeader>
|
||||
<IonContent>
|
||||
<IonHeader collapse="condense">
|
||||
<IonToolbar>
|
||||
<IonTitle size="large">
|
||||
Szczegóły
|
||||
</IonTitle>
|
||||
</IonToolbar>
|
||||
</IonHeader>
|
||||
{currentlySelectedWarning !== undefined && currentlySelectedWarning !== null && (
|
||||
<IonList lines="full">
|
||||
<IonItem>
|
||||
<IonLabel>
|
||||
{(currentlySelectedWarning as any).col3.val}
|
||||
</IonLabel>
|
||||
</IonItem>
|
||||
<IonItem>
|
||||
<IonLabel>
|
||||
{(currentlySelectedWarning as any).col2.val}
|
||||
</IonLabel>
|
||||
</IonItem>
|
||||
<IonItem>
|
||||
<IonLabel>
|
||||
{(currentlySelectedWarning as any).col5.val}
|
||||
</IonLabel>
|
||||
</IonItem>
|
||||
<IonItem>
|
||||
<IonLabel>
|
||||
{(currentlySelectedWarning as any).col6.val}
|
||||
</IonLabel>
|
||||
</IonItem>
|
||||
<IonItem>
|
||||
<IonLabel>
|
||||
{(currentlySelectedWarning as any).col7.val}
|
||||
</IonLabel>
|
||||
</IonItem>
|
||||
<IonItem>
|
||||
<IonLabel>
|
||||
{(currentlySelectedWarning as any).col9.val}
|
||||
</IonLabel>
|
||||
</IonItem>
|
||||
</IonList>
|
||||
)}
|
||||
</IonContent>
|
||||
</IonModal>
|
||||
<IonInfiniteScroll onIonInfinite={onIonScroll}>
|
||||
<IonInfiniteScrollContent />
|
||||
</IonInfiniteScroll>
|
||||
</>
|
||||
</>
|
||||
) : <></>;
|
||||
};
|
||||
|
|
6
src/Nyanlabs.SFood.UI/sfood/src/pages/Home.module.css
Normal file
6
src/Nyanlabs.SFood.UI/sfood/src/pages/Home.module.css
Normal file
|
@ -0,0 +1,6 @@
|
|||
.addWarningButtonDiv {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
|
@ -2,23 +2,27 @@ import { IonContent, IonHeader, IonPage, IonTitle, IonToolbar } from '@ionic/rea
|
|||
|
||||
import WarningsList from '../components/WarningsList/WarningsList';
|
||||
import Search from '../components/Search/Search';
|
||||
import AddWarningButton from '../components/AddWarningButton/AddWarningButton';
|
||||
|
||||
import './Home.css';
|
||||
import styles from './Home.module.css';
|
||||
|
||||
const Home: React.FC = () => {
|
||||
return (
|
||||
<IonPage>
|
||||
<IonHeader>
|
||||
<IonToolbar>
|
||||
<IonTitle>Bezpieczna żywnosc</IonTitle>
|
||||
<IonTitle>Bezpieczna żywność</IonTitle>
|
||||
</IonToolbar>
|
||||
</IonHeader>
|
||||
<IonContent fullscreen>
|
||||
<IonHeader collapse="condense">
|
||||
<IonToolbar>
|
||||
<IonTitle size="large">Bezpieczna żywnosc</IonTitle>
|
||||
<IonTitle size="large">Bezpieczna żywność</IonTitle>
|
||||
</IonToolbar>
|
||||
</IonHeader>
|
||||
<div className={`${styles.addWarningButtonDiv} ion-padding-horizontal`}>
|
||||
<AddWarningButton />
|
||||
</div>
|
||||
<Search />
|
||||
<WarningsList />
|
||||
</IonContent>
|
||||
|
|
Loading…
Reference in a new issue