diff --git a/frontend/src/TempData/RegionOptions.ts b/frontend/src/TempData/RegionOptions.ts new file mode 100644 index 00000000..415d7c40 --- /dev/null +++ b/frontend/src/TempData/RegionOptions.ts @@ -0,0 +1,8 @@ +const RegionOptions = [ + { value: 0, label: 'Select a region' }, + { value: 1, label: 'Bulkley-Nechako' }, + { value: 2, label: 'Cariboo' }, + { value: 3, label: 'Columbia Shuswap' }, +]; + +export default RegionOptions; diff --git a/frontend/src/components/common/Modal/Modal.tsx b/frontend/src/components/common/Modal/Modal.tsx new file mode 100644 index 00000000..cf33e679 --- /dev/null +++ b/frontend/src/components/common/Modal/Modal.tsx @@ -0,0 +1,36 @@ +import React from 'react'; +import { + ModalWrapper, + ModalContent, + ModalHeader, + ModalBody, + ModalFooter, + CloseButton, +} from './modal.styles'; + +interface ModalProps { + isVisible: boolean; + title: string; + children: React.ReactNode; + onClose: () => void; + footer?: React.ReactNode; +} + +function Modal({ isVisible, title, children, onClose, footer }: ModalProps) { + if (!isVisible) return null; + + return ( + + + +

{title}

+ × +
+ {children} + {footer && {footer}} +
+
+ ); +} + +export default Modal; diff --git a/frontend/src/components/common/Modal/modal.styles.ts b/frontend/src/components/common/Modal/modal.styles.ts new file mode 100644 index 00000000..6c0cf2b3 --- /dev/null +++ b/frontend/src/components/common/Modal/modal.styles.ts @@ -0,0 +1,50 @@ +import styled from '@emotion/styled'; + +export const ModalWrapper = styled.div` + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: rgba(0, 0, 0, 0.5); + display: flex; + justify-content: center; + align-items: center; + z-index: 3000; +`; + +export const ModalContent = styled.div` + background: #fff; + padding: 20px; + border-radius: 8px; + width: 500px; + max-width: 100%; +`; + +export const ModalHeader = styled.div` + display: flex; + justify-content: space-between; + align-items: center; + border-bottom: 1px solid #ccc; + padding-bottom: 10px; + margin-bottom: 20px; +`; + +export const ModalBody = styled.div` + padding-bottom: 20px; +`; + +export const ModalFooter = styled.div` + display: flex; + justify-content: flex-end; + border-top: 1px solid #ccc; + padding-top: 10px; + margin-top: 20px; +`; + +export const CloseButton = styled.button` + background: none; + border: none; + font-size: 24px; + cursor: pointer; +`; diff --git a/frontend/src/components/common/Tabs/Tabs.tsx b/frontend/src/components/common/Tabs/Tabs.tsx new file mode 100644 index 00000000..0a83c2cc --- /dev/null +++ b/frontend/src/components/common/Tabs/Tabs.tsx @@ -0,0 +1,41 @@ +import React from 'react'; +import { TabsWrapper, Tab, TabContent } from './tabs.styles'; + +interface TabProps { + label: string; + content: React.ReactNode; + id: string; +} + +interface TabsProps { + tabs: TabProps[]; + activeTab: number; + setActiveTab?: (index: number) => void; +} + +export function TabOptions({ tabs, activeTab, setActiveTab }: TabsProps) { + return ( + +
+ {tabs.map((tab, index) => ( + setActiveTab && setActiveTab(index)} + > + {tab.label} + + ))} +
+
+ ); +} + +interface TabContentDisplayProps { + tabs: TabProps[]; + activeTab: number; +} + +export function TabContentDisplay({ tabs, activeTab }: TabContentDisplayProps) { + return {tabs[activeTab].content}; +} diff --git a/frontend/src/components/common/Tabs/tabs.styles.ts b/frontend/src/components/common/Tabs/tabs.styles.ts new file mode 100644 index 00000000..9d6d1ea7 --- /dev/null +++ b/frontend/src/components/common/Tabs/tabs.styles.ts @@ -0,0 +1,27 @@ +import styled from '@emotion/styled'; + +export const TabsWrapper = styled.div` + display: flex; + flex-direction: column; +`; + +export const Tab = styled.button<{ active: boolean }>` + padding: 10px 20px; + cursor: pointer; + background-color: ${({ active }) => (active ? '#036' : '#ccc')}; + color: ${({ active }) => (active ? '#fff' : '#000')}; + border: none; + border-bottom: ${({ active }) => (active ? '2px solid #fcba19' : 'none')}; + border-radius: 5px; + height: 50px; + &:hover { + background-color: #036; + color: #fff; + } +`; + +export const TabContent = styled.div` + padding: 20px; + background-color: #fff; + width: 100%; +`; diff --git a/frontend/src/components/common/index.ts b/frontend/src/components/common/index.ts index a1aa5b01..7df0eab7 100644 --- a/frontend/src/components/common/index.ts +++ b/frontend/src/components/common/index.ts @@ -6,5 +6,6 @@ import RadioButton from './RadioButton/RadioButton'; import Checkbox from './Checkbox/Checkbox'; import Dropdown from './DropDown/DropDown'; import Card from './Card/Card'; +import Modal from './Modal/Modal'; -export { Header, Button, Footer, InputField, RadioButton, Checkbox, Dropdown, Card }; +export { Header, Button, Footer, InputField, RadioButton, Checkbox, Dropdown, Card, Modal }; diff --git a/frontend/src/routes/ViewRouter.tsx b/frontend/src/routes/ViewRouter.tsx index bde28b85..7aedfa0f 100644 --- a/frontend/src/routes/ViewRouter.tsx +++ b/frontend/src/routes/ViewRouter.tsx @@ -6,6 +6,7 @@ import { Routes, Route } from 'react-router-dom'; import LandingPage from '../views/LandingPage/LandingPage'; import FarmInformation from '../views/FarmInformation/FarmInformation'; import AdminDashboard from '@/views/AdminDashboard/AdminDashboard'; +import FieldAndSoil from '@/views/FieldAndSoil/FieldAndSoil'; export default function ViewRouter() { return ( @@ -22,6 +23,10 @@ export default function ViewRouter() { path="/admin" Component={AdminDashboard} /> + ); } diff --git a/frontend/src/views/FarmInformation/FarmInformation.tsx b/frontend/src/views/FarmInformation/FarmInformation.tsx index 3fc8205b..efebbadd 100644 --- a/frontend/src/views/FarmInformation/FarmInformation.tsx +++ b/frontend/src/views/FarmInformation/FarmInformation.tsx @@ -2,9 +2,11 @@ * @summary The Farm Information page for the application */ import React, { useState, useEffect } from 'react'; +import { useNavigate } from 'react-router-dom'; import useAppService from '@/services/app/useAppService'; import NMPFile from '@/types/NMPFile'; import defaultNMPFile from '../../constants/DefaultNMPFile'; +import RegionOptions from '../../TempData/RegionOptions'; import { CardHeader, Banner, @@ -18,6 +20,7 @@ import { InputField, RadioButton, Checkbox, Dropdown, Card, Button } from '../.. export default function FarmInformation() { const { state, setNMPFile } = useAppService(); + const navigate = useNavigate(); const [formData, setFormData] = useState({ Year: '', FarmName: '', @@ -49,13 +52,6 @@ export default function FarmInformation() { setFormData({ ...formData, [name]: type === 'checkbox' ? checked : value }); }; - const regionOptions = [ - { value: 0, label: 'Select a region' }, - { value: 1, label: 'Bulkley-Nechako' }, - { value: 2, label: 'Cariboo' }, - { value: 3, label: 'Columbia Shuswap' }, - ]; - const handleSubmit = () => { let nmpFile: NMPFile; @@ -65,6 +61,7 @@ export default function FarmInformation() { nmpFile.farmDetails = { ...nmpFile.farmDetails, ...formData }; setNMPFile(JSON.stringify(nmpFile)); + navigate('/field-and-soil'); }; return ( @@ -101,7 +98,7 @@ export default function FarmInformation() { label="Region" name="FarmRegion" value={formData.FarmRegion} - options={regionOptions} + options={RegionOptions} onChange={handleChange} flex="0.35" /> @@ -143,7 +140,7 @@ export default function FarmInformation() { + + + ))} + + setIsModalVisible(false)} + footer={ + + } + > + + + + + + + ); +} diff --git a/frontend/src/views/FieldAndSoil/FieldList/fieldList.styles.ts b/frontend/src/views/FieldAndSoil/FieldList/fieldList.styles.ts new file mode 100644 index 00000000..1eb25afe --- /dev/null +++ b/frontend/src/views/FieldAndSoil/FieldList/fieldList.styles.ts @@ -0,0 +1,15 @@ +/** + * @summary Styling for FieldList view + */ +import styled from '@emotion/styled'; + +const ListItemContainer = styled.div` + display: flex; + gap: 16px; + margin-top: 16px; + width: 100%; + justify-content: flex-start; + align-items: center; +`; + +export default ListItemContainer; diff --git a/frontend/src/views/FieldAndSoil/fieldAndSoil.styles.ts b/frontend/src/views/FieldAndSoil/fieldAndSoil.styles.ts new file mode 100644 index 00000000..f28860a1 --- /dev/null +++ b/frontend/src/views/FieldAndSoil/fieldAndSoil.styles.ts @@ -0,0 +1,42 @@ +/** + * @summary Styling for FieldList view + */ +import styled from '@emotion/styled'; +import screenSizes from '../../constants/screenSizes'; + +export const CardHeader = styled.div` + background-color: rgba(200, 200, 200, 0.3); + padding: 0; + color: #fff; + display: flex; + justify-content: space-between; + align-items: center; + height: 65px; + width: 100%; + position: absolute; + top: 0; + left: 0; + border-top-left-radius: 8px; + border-top-right-radius: 8px; + @media (min-width: ${screenSizes.tablet}) { + justify-content: flex-start; + padding-left: 2em; + } + z-index: 2000; +`; + +export const Banner = styled.div` + display: flex; + align-items: center; + margin: 0; +`; + +export const ButtonWrapper = styled.div<{ position?: 'left' | 'right' }>` + position: absolute; + bottom: 16px; + ${({ position }) => (position === 'left' ? 'left: 16px;' : 'right: 16px;')} + button { + width: 80px; + height: 40px; + } +`;