Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Common card component #100

Merged
merged 2 commits into from
Dec 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions frontend/src/App.styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,19 @@ import styled from '@emotion/styled';
/**
* @summary This is the root styling for the application.
*/
const StyledApp = styled.div`
export const StyledApp = styled.div`
display: flex;
flex-direction: column;
min-height: 100vh;
`;

export default StyledApp;
export const ViewContainer = styled.div`
position: absolute;
top: 0;
left: 0;
display: flex;
height: 100svh;
justify-content: center;
width: 100%;
align-items: center;
`;
6 changes: 4 additions & 2 deletions frontend/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import StyledApp from './App.styles';
import { StyledApp, ViewContainer } from './App.styles';
import { Header, Footer } from './components/common';
import ViewRouter from './routes/ViewRouter';

Expand All @@ -9,7 +9,9 @@ function App() {
return (
<StyledApp>
<Header />
<ViewRouter />
<ViewContainer>
<ViewRouter />
</ViewContainer>
<Footer />
</StyledApp>
);
Expand Down
31 changes: 31 additions & 0 deletions frontend/src/components/common/Card/Card.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/**
* @summary A reusable Card component
*/
import React from 'react';
import { CardWrapper } from './card.styles';

interface CardProps {
children: React.ReactNode;
width?: string;
height?: string;
justifyContent?: string;
}

function Card({
children,
width = '500px',
height = '500px',
justifyContent = 'center',
}: CardProps) {
return (
<CardWrapper
width={width}
height={height}
justifyContent={justifyContent}
>
{children}
</CardWrapper>
);
}

export default Card;
30 changes: 30 additions & 0 deletions frontend/src/components/common/Card/card.styles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/**
* @summary Styling for Card component
*/
import styled from '@emotion/styled';

type CardWrapperProps = {
width: string;
height: string;
justifyContent?: string;
};

export const CardWrapper = styled.div<CardWrapperProps>`
background-color: rgba(255, 255, 255, 0.8);
height: ${(props) => props.height};
width: ${(props) => props.width};
padding-top: 0;
justify-content: flex-start;
align-items: center;
display: flex;
flex-direction: column;
object-fit: scale-down;
border-radius: 8px;
box-shadow: 0 8px 16px rgba(0, 0, 0, 0.1);
padding: 20px;
text-align: center;
position: relative;
justify-content: ${(props) => props.justifyContent};
`;

export default CardWrapper;
3 changes: 2 additions & 1 deletion frontend/src/components/common/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@ import InputField from './InputField/InputField';
import RadioButton from './RadioButton/RadioButton';
import Checkbox from './Checkbox/Checkbox';
import Dropdown from './DropDown/DropDown';
import Card from './Card/Card';

export { Header, Button, Footer, InputField, RadioButton, Checkbox, Dropdown };
export { Header, Button, Footer, InputField, RadioButton, Checkbox, Dropdown, Card };
136 changes: 68 additions & 68 deletions frontend/src/views/FarmInformation/FarmInformation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,14 @@ import React, { useState, useEffect } from 'react';
import { localStorageKeyExists } from '../../utils/AppLocalStorage';
import constants from '../../constants/Constants';
import {
ViewContainer,
Card,
CardHeader,
Banner,
Heading,
InputFieldsContainer,
SelectorContainer,
RegionContainer,
} from './farmInformation.styles';
import { InputField, RadioButton, Checkbox, Dropdown } from '../../components/common';
import { InputField, RadioButton, Checkbox, Dropdown, Card } from '../../components/common';

export default function FarmInformation() {
const [formData, setFormData] = useState({
Expand Down Expand Up @@ -61,76 +59,78 @@ export default function FarmInformation() {
];

return (
<ViewContainer>
<Card>
<CardHeader>
<Banner>
<Heading>Farm Information</Heading>
</Banner>
</CardHeader>
<InputFieldsContainer>
<InputField
label="Year"
type="text"
name="Year"
value={formData.Year}
onChange={handleChange}
flex="0.5"
/>
<InputField
label="Farm Name"
type="text"
name="FarmName"
value={formData.FarmName}
onChange={handleChange}
flex="1"
/>
</InputFieldsContainer>
<RegionContainer>
<Dropdown
label="Region"
name="FarmRegion"
value={formData.FarmRegion}
options={regionOptions}
onChange={handleChange}
flex="0.35"
/>
</RegionContainer>
<Card
height="500px"
width="600px"
justifyContent="flex-start"
>
<CardHeader>
<Banner>
<Heading>Farm Information</Heading>
</Banner>
</CardHeader>
<InputFieldsContainer>
<InputField
label="Year"
type="text"
name="Year"
value={formData.Year}
onChange={handleChange}
flex="0.5"
/>
<InputField
label="Farm Name"
type="text"
name="FarmName"
value={formData.FarmName}
onChange={handleChange}
flex="1"
/>
</InputFieldsContainer>
<RegionContainer>
<Dropdown
label="Region"
name="FarmRegion"
value={formData.FarmRegion}
options={regionOptions}
onChange={handleChange}
flex="0.35"
/>
</RegionContainer>
<SelectorContainer>
<span style={{ marginRight: '8px' }}>I have crops</span>
<RadioButton
label="Yes"
name="Crops"
value="true"
checked={formData.Crops === 'true'}
onChange={handleChange}
/>
<RadioButton
label="No"
name="Crops"
value="false"
checked={formData.Crops === 'false'}
onChange={handleChange}
/>
</SelectorContainer>
{formData.Crops === 'true' && (
<SelectorContainer>
<span style={{ marginRight: '8px' }}>I have crops</span>
<RadioButton
label="Yes"
name="Crops"
value="true"
checked={formData.Crops === 'true'}
<span style={{ marginRight: '8px' }}>Select your crops:</span>
<Checkbox
label="Vegetables"
name="HasVegetables"
checked={formData.HasVegetables}
onChange={handleChange}
/>
<RadioButton
label="No"
name="Crops"
value="false"
checked={formData.Crops === 'false'}
<Checkbox
label="Berries"
name="HasBerries"
checked={formData.HasBerries}
onChange={handleChange}
/>
</SelectorContainer>
{formData.Crops === 'true' && (
<SelectorContainer>
<span style={{ marginRight: '8px' }}>Select your crops:</span>
<Checkbox
label="Vegetables"
name="HasVegetables"
checked={formData.HasVegetables}
onChange={handleChange}
/>
<Checkbox
label="Berries"
name="HasBerries"
checked={formData.HasBerries}
onChange={handleChange}
/>
</SelectorContainer>
)}
</Card>
</ViewContainer>
)}
</Card>
);
}
11 changes: 0 additions & 11 deletions frontend/src/views/FarmInformation/farmInformation.styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,6 @@
import styled from '@emotion/styled';
import screenSizes from '../../constants/screenSizes';

export const ViewContainer = styled.div`
position: absolute;
top: 0;
left: 0;
display: flex;
height: 100svh;
justify-content: center;
width: 100%;
align-items: center;
`;

export const Card = styled.div`
background-color: rgba(255, 255, 255, 0.8);
height: 500px;
Expand Down
96 changes: 46 additions & 50 deletions frontend/src/views/LandingPage/LandingPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,8 @@ import { useNavigate } from 'react-router-dom';
import constants from '../../constants/Constants';
import useAppService from '../../services/app/useAppService';
import { deleteLocalStorageKey } from '../../utils/AppLocalStorage';
import {
ButtonWrapper,
ViewContainer,
StyledDivider,
StyledContent,
Card,
} from './landingPage.styles';
import { Button } from '../../components/common';
import { ButtonWrapper, StyledDivider, StyledContent } from './landingPage.styles';
import { Button, Card } from '../../components/common';

export default function LandingPage() {
const { setNMPFile } = useAppService();
Expand Down Expand Up @@ -48,47 +42,49 @@ export default function LandingPage() {
};

return (
<ViewContainer>
<Card>
<StyledContent>
<h1>Nutrient Management Calculator</h1>
<p>
The Nutrient Management Calculator provides a starting point for the efficient use of
fertilizer and manure on farms. This tool assists in you choosing the right rate and
nutrient source for your crops. You can start a new calculation or pick up where you
left off by uploading an existing .nmp file.
</p>
</StyledContent>
<ButtonWrapper>
<Button
text="Start a new calculation"
size="lg"
handleClick={newCalcHandler}
aria-label="Start a new calculation"
variant="primary"
disabled={false}
/>
</ButtonWrapper>
<StyledDivider>or</StyledDivider>
<ButtonWrapper>
<Button
size="lg"
text="Upload an existing .nmp file"
handleClick={handleUpload}
aria-label="Upload an existing .nmp file"
variant="primary"
disabled={false}
/>
<input
id="fileUp"
type="file"
accept=".nmp, application/json"
onChange={saveFile}
aria-label="Upload an existing .nmp file"
hidden
/>
</ButtonWrapper>
</Card>
</ViewContainer>
<Card
width="500px"
height="500px"
justifyContent="center"
>
<StyledContent>
<h1>Nutrient Management Calculator</h1>
<p>
The Nutrient Management Calculator provides a starting point for the efficient use of
fertilizer and manure on farms. This tool assists in you choosing the right rate and
nutrient source for your crops. You can start a new calculation or pick up where you left
off by uploading an existing .nmp file.
</p>
</StyledContent>
<ButtonWrapper>
<Button
text="Start a new calculation"
size="lg"
handleClick={newCalcHandler}
aria-label="Start a new calculation"
variant="primary"
disabled={false}
/>
</ButtonWrapper>
<StyledDivider>or</StyledDivider>
<ButtonWrapper>
<Button
size="lg"
text="Upload an existing .nmp file"
handleClick={handleUpload}
aria-label="Upload an existing .nmp file"
variant="primary"
disabled={false}
/>
<input
id="fileUp"
type="file"
accept=".nmp, application/json"
onChange={saveFile}
aria-label="Upload an existing .nmp file"
hidden
/>
</ButtonWrapper>
</Card>
);
}
Loading
Loading