Skip to content

Commit

Permalink
feat: [NR-NMP-111] "I have animals" radio buttons (#146)
Browse files Browse the repository at this point in the history
  • Loading branch information
raarielgrace authored Jan 24, 2025
1 parent 4ee3750 commit f2d4648
Show file tree
Hide file tree
Showing 24 changed files with 358 additions and 80 deletions.
Empty file.
4 changes: 4 additions & 0 deletions backend/apps/animals/admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
from django.contrib import admin
from .models import Animals

admin.site.register(Animals)
10 changes: 10 additions & 0 deletions backend/apps/animals/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
from django.db import models

class Animals(models.Model):
id = models.IntegerField(primary_key=True)
name = models.CharField(max_length=100)
usesortorder = models.BooleanField()

class Meta:
managed = False
db_table = 'animals'
7 changes: 7 additions & 0 deletions backend/apps/animals/serializers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
from rest_framework import serializers
from .models import Animals

class AnimalsSerializer(serializers.ModelSerializer):
class Meta:
model = Animals
fields = '__all__'
1 change: 1 addition & 0 deletions backend/apps/api/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,5 @@

urlpatterns = [
path('croptypes/', views.APIViewSet.as_view({'get': 'cropTypes'}), name='cropTypes'),
path('animals/', views.APIViewSet.as_view({'get': 'animals'}), name='animals'),
]
9 changes: 9 additions & 0 deletions backend/apps/api/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,19 @@
from rest_framework.response import Response
from apps.crops.models import CropTypes
from apps.crops.serializers import CropTypesSerializer
from apps.animals.models import *
from apps.animals.serializers import *

class APIViewSet(viewsets.ViewSet):

@action(detail=True, methods=['get'])
def cropTypes(self, request, pk=None):
crop_types = CropTypes.objects.all()
serializer = CropTypesSerializer(crop_types, many=True)
return Response(serializer.data, status=status.HTTP_200_OK)

@action(detail=True, methods=['get'])
def animals(self, request, pk=None):
animals = Animals.objects.all()
serializer = AnimalsSerializer(animals, many=True)
return Response(serializer.data, status=status.HTTP_200_OK)
5 changes: 0 additions & 5 deletions backend/apps/crops/models.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,6 @@
from django.db import models

class CropTypes(models.Model):
# This model errors because it doesn't have a primary key
# Django tries to treat id as the primary key but it's non-unique
# Trying to add some fake primary key that doesn't exist in the table also errors
# This composite key is only supported in an alpha build of Django
# But even the alpha build doesn't support composite keys on the admin portal
id = models.IntegerField(primary_key=True)
name = models.CharField(max_length=100)
covercrop = models.BooleanField()
Expand Down
1 change: 1 addition & 0 deletions backend/config/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@
# Apps for this project
'apps.api',
'apps.crops',
'apps.animals',
]

MIDDLEWARE = [
Expand Down
117 changes: 117 additions & 0 deletions database/db/seed_tables/_Animals/_Animals__20241212.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
Id,Name,UseSortOrder,StaticDataVersionId
9,Swine,FALSE,1
6,Poultry,FALSE,1
8,Sheep,FALSE,1
10,Veal,FALSE,1
7,Rabbits,FALSE,1
2,Dairy Cattle,TRUE,1
4,Goats,FALSE,1
3,Ducks,FALSE,1
1,Beef Cattle,FALSE,1
5,Horse,FALSE,1
5,Horse,FALSE,2
1,Beef Cattle,FALSE,2
3,Ducks,FALSE,2
2,Dairy Cattle,TRUE,2
4,Goats,FALSE,2
10,Veal,FALSE,2
8,Sheep,FALSE,2
6,Poultry,FALSE,2
9,Swine,FALSE,2
7,Rabbits,FALSE,2
7,Rabbits,FALSE,3
9,Swine,FALSE,3
6,Poultry,FALSE,3
10,Veal,FALSE,3
8,Sheep,FALSE,3
2,Dairy Cattle,TRUE,3
3,Ducks,FALSE,3
1,Beef Cattle,FALSE,3
5,Horse,FALSE,3
4,Goats,FALSE,3
4,Goats,FALSE,4
5,Horse,FALSE,4
1,Beef Cattle,FALSE,4
2,Dairy Cattle,TRUE,4
3,Ducks,FALSE,4
10,Veal,FALSE,4
6,Poultry,FALSE,4
9,Swine,FALSE,4
7,Rabbits,FALSE,4
8,Sheep,FALSE,4
8,Sheep,FALSE,5
7,Rabbits,FALSE,5
9,Swine,FALSE,5
10,Veal,FALSE,5
6,Poultry,FALSE,5
2,Dairy Cattle,TRUE,5
1,Beef Cattle,FALSE,5
5,Horse,FALSE,5
4,Goats,FALSE,5
3,Ducks,FALSE,5
3,Ducks,FALSE,6
4,Goats,FALSE,6
5,Horse,FALSE,6
2,Dairy Cattle,TRUE,6
1,Beef Cattle,FALSE,6
10,Veal,FALSE,6
9,Swine,FALSE,6
7,Rabbits,FALSE,6
8,Sheep,FALSE,6
6,Poultry,FALSE,6
8,Sheep,FALSE,7
7,Rabbits,FALSE,7
9,Swine,FALSE,7
6,Poultry,FALSE,7
4,Goats,FALSE,7
1,Beef Cattle,FALSE,7
5,Horse,FALSE,7
2,Dairy Cattle,TRUE,7
2,Dairy Cattle,TRUE,8
5,Horse,FALSE,8
1,Beef Cattle,FALSE,8
4,Goats,FALSE,8
8,Sheep,FALSE,8
9,Swine,FALSE,8
7,Rabbits,FALSE,8
6,Poultry,FALSE,8
6,Poultry,FALSE,9
7,Rabbits,FALSE,9
9,Swine,FALSE,9
8,Sheep,FALSE,9
2,Dairy Cattle,TRUE,9
1,Beef Cattle,FALSE,9
5,Horse,FALSE,9
4,Goats,FALSE,9
4,Goats,FALSE,10
5,Horse,FALSE,10
1,Beef Cattle,FALSE,10
2,Dairy Cattle,TRUE,10
6,Poultry,FALSE,10
9,Swine,FALSE,10
7,Rabbits,FALSE,10
8,Sheep,FALSE,10
9,Swine,FALSE,12
8,Sheep,FALSE,12
7,Rabbits,FALSE,12
6,Poultry,FALSE,12
1,Beef Cattle,FALSE,12
4,Goats,FALSE,12
2,Dairy Cattle,TRUE,12
5,Horse,FALSE,12
1,Beef Cattle,FALSE,13
2,Dairy Cattle,TRUE,13
4,Goats,FALSE,13
5,Horse,FALSE,13
6,Poultry,FALSE,13
7,Rabbits,FALSE,13
8,Sheep,FALSE,13
9,Swine,FALSE,13
1,Beef Cattle,FALSE,14
2,Dairy Cattle,TRUE,14
4,Goats,FALSE,14
5,Horse,FALSE,14
6,Poultry,FALSE,14
7,Rabbits,FALSE,14
8,Sheep,FALSE,14
9,Swine,FALSE,14
13 changes: 13 additions & 0 deletions database/db/seed_tables/_Animals/init_animals.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
CREATE TABLE IF NOT EXISTS temp_animals (
Id INT NOT NULL,
Name VARCHAR(100) NOT NULL,
UseSortOrder BOOLEAN NOT NULL,
StaticDataVersionId INT NOT NULL,
PRIMARY KEY (Id, StaticDataVersionId)
);
\copy temp_animals (Id, Name, UseSortOrder, StaticDataVersionId) from 'docker-entrypoint-initdb.d/_Animals__20241212.csv' with header delimiter ',' CSV ;
SELECT * INTO animals
FROM temp_animals
WHERE StaticDataVersionId=14;
ALTER TABLE animals
DROP COLUMN StaticDataVersionId;
9 changes: 9 additions & 0 deletions database/db/trimmed_tables/_Animals/_Animals_202501201453.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
"id","name","usesortorder"
1,Beef Cattle,false
2,Dairy Cattle,true
4,Goats,false
5,Horse,false
6,Poultry,false
7,Rabbits,false
8,Sheep,false
9,Swine,false
6 changes: 6 additions & 0 deletions database/db/trimmed_tables/_Animals/init_animals.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
CREATE TABLE IF NOT EXISTS animals (
Id INT PRIMARY KEY,
Name VARCHAR(100) NOT NULL,
UseSortOrder BOOLEAN NOT NULL
);
\copy animals (Id, Name, UseSortOrder) from 'docker-entrypoint-initdb.d/_Animals_202501201453.csv' with header delimiter ',' CSV ;
12 changes: 7 additions & 5 deletions frontend/src/components/common/Button/Button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,13 @@ export type ButtonProps = {
text: string;
};

export function Button({ handleClick, variant, size = 'md', disabled = false, text }: ButtonProps) {
export function Button({
handleClick = () => {},
variant,
size = 'md',
disabled = false,
text,
}: ButtonProps) {
return (
<StyledButton
onClick={handleClick}
Expand All @@ -35,7 +41,3 @@ export function Button({ handleClick, variant, size = 'md', disabled = false, te
</StyledButton>
);
}

Button.defaultProps = {
handleClick: () => {}, // Provide a default empty function
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import React, { useState } from 'react';
// Make own style file if necessary
import { SelectorContainer } from '@/views/FarmInformation/farmInformation.styles';
import RadioButton from '../RadioButton/RadioButton';

interface YesNoRadioButtonProps {
name: string;
text: string;
handleYes: (e: React.ChangeEvent<HTMLInputElement>) => void;
handleNo: (e: React.ChangeEvent<HTMLInputElement>) => void;
}

function YesNoRadioButtons({ name, text, handleYes, handleNo }: YesNoRadioButtonProps) {
const [isYes, setIsYes] = useState<boolean>(false);
return (
<SelectorContainer>
<span style={{ marginRight: '8px' }}>{text}</span>
<RadioButton
label="Yes"
name={name}
value="true"
checked={isYes}
onChange={(e) => {
setIsYes(true);
handleYes(e);
}}
/>
<RadioButton
label="No"
name={name}
value="false"
checked={!isYes}
onChange={(e) => {
setIsYes(false);
handleNo(e);
}}
/>
</SelectorContainer>
);
}

export default YesNoRadioButtons;
12 changes: 12 additions & 0 deletions frontend/src/context/APICacheContext.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import React, { createContext } from 'react';
import APICache from '@/types/APICache';

const cache = new APICache();
const APICacheContext = createContext(cache);

function APICacheProvider(props: { children: React.ReactNode }) {
const { children } = props;
return <APICacheContext.Provider value={cache}>{children}</APICacheContext.Provider>;
}

export { APICacheContext, APICacheProvider };
File renamed without changes.
File renamed without changes.
11 changes: 7 additions & 4 deletions frontend/src/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,17 @@ import { StrictMode } from 'react';
import { createRoot } from 'react-dom/client';
import { BrowserRouter } from 'react-router-dom';
import App from './App.tsx';
import AppProvider from './providers/AppProvider.tsx';
import AppProvider from './context/AppProvider.tsx';
import { APICacheProvider } from './context/APICacheContext.tsx';

createRoot(document.getElementById('root')!).render(
<StrictMode>
<AppProvider>
<BrowserRouter>
<App />
</BrowserRouter>
<APICacheProvider>
<BrowserRouter>
<App />
</BrowserRouter>
</APICacheProvider>
</AppProvider>
</StrictMode>,
);
5 changes: 0 additions & 5 deletions frontend/src/routes/ViewRouter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ 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() {
Expand All @@ -19,10 +18,6 @@ export default function ViewRouter() {
path="/farm-information"
Component={FarmInformation}
/>
<Route
path="/admin"
Component={AdminDashboard}
/>
<Route
path="/field-and-soil"
Component={FieldAndSoil}
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/services/app/useAppService.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/* eslint-disable no-console */
import { useContext, useMemo } from 'react';
import constants from '../../constants/Constants';
import { AppContext } from '../../providers/AppProvider';
import { AppContext } from '../../context/AppProvider';
import AppActionType from './AppActions';
import { saveDataToLocalStorage } from '../../utils/AppLocalStorage';

Expand Down
17 changes: 17 additions & 0 deletions frontend/src/types/APICache.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import axios, { AxiosResponse } from 'axios';

class APICache {
private endpointCache: { [endpoint: string]: AxiosResponse } = {};

async callEndpoint(endpoint: string) {
const cachedValue = this.endpointCache[endpoint];
if (cachedValue !== undefined && cachedValue.status === 200) {
return cachedValue;
}
const response = await axios.get(`http://localhost:3000/${endpoint}`);
this.endpointCache[endpoint] = response;
return response;
}
}

export default APICache;
9 changes: 0 additions & 9 deletions frontend/src/views/AdminDashboard/AdminDashboard.tsx

This file was deleted.

Loading

0 comments on commit f2d4648

Please sign in to comment.