Skip to content
Open
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
14 changes: 14 additions & 0 deletions BeerApp - Senior/jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
module.exports = {
preset: 'ts-jest',
testEnvironment: 'node',
setupFilesAfterEnv: ['<rootDir>/src/setupTests.ts'],
moduleDirectories: ['node_modules', 'src'],
collectCoverage: true,
collectCoverageFrom: ['src/**/*.ts', 'src/**/*.tsx'],
coverageReporters: ['json-summary', 'text', 'lcov'],
extensionsToTreatAsEsm: ['.ts'],
transform: {
'^.+\\.tsx?$': 'ts-jest',
},
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'],
};
1,023 changes: 778 additions & 245 deletions BeerApp - Senior/package-lock.json

Large diffs are not rendered by default.

15 changes: 12 additions & 3 deletions BeerApp - Senior/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,28 +8,37 @@
"@fontsource/roboto": "^4.5.8",
"@mui/icons-material": "^5.11.16",
"@mui/material": "^5.13.0",
"@popperjs/core": "^2.11.8",
"axios": "^1.4.0",
"leaflet": "^1.9.4",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-leaflet": "^4.2.1",
"react-router-dom": "^6.11.1"
},
"devDependencies": {
"@babel/preset-typescript": "^7.23.3",
"@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
"@types/jest": "^27.5.2",
"@types/leaflet": "^1.9.8",
"@types/node": "^16.18.28",
"@types/react": "^18.2.6",
"@types/react-dom": "^18.2.4",
"jest": "^27.4.7",
"react-scripts": "5.0.1",
"react-test-renderer": "^18.0.0",
"ts-jest": "^27.0.7",
"typescript": "^4.9.5",
"typescript-plugin-css-modules": "^5.0.1"
"typescript-plugin-css-modules": "^5.0.1",
"workbox-webpack-plugin": "^7.0.0"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
"eject": "react-scripts eject",
"test": "react-scripts test --transformIgnorePatterns \"node_modules/(?!axios)/\""
},
"eslintConfig": {
"extends": [
Expand Down
37 changes: 37 additions & 0 deletions BeerApp - Senior/public/service-worker.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// public/service-worker.js
const CACHE_NAME = 'beer-app-cache';
self.addEventListener('install', (event) => {
const urlsToCache = [
'/',
'/index.html',
// Add other URLs you want to cache...
];

event.waitUntil(
caches.open(CACHE_NAME).then((cache) => {
return cache.addAll(urlsToCache);
})
);
});

self.addEventListener('fetch', (event) => {
event.respondWith(
// Try to fetch the request from the network
fetch(event.request).then((response) => {
// If the fetch is successful, clone the response and cache it
if (response.ok) {
const clone = response.clone();
caches.open(CACHE_NAME).then((cache) => {
cache.put(event.request, clone);
});
}
return response;
}).catch(() => {
// If the fetch fails (e.g., when offline), try to respond with the cached version
return caches.match(event.request).then((cachedResponse) => {
return cachedResponse || new Response('', { status: 404, statusText: 'Not Found' });
});
})
);
});

4 changes: 3 additions & 1 deletion BeerApp - Senior/src/api/beer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ const getBeer = (id: string) => axios.get(`${API}breweries/${id}`);

const getBeerList = (params?: ApiParams) => axios.get(`${API}breweries/`, { params });

const getFavouriteListByIds = (by_ids: string) => axios.get(`${API}breweries`, { params: { by_ids } });

/**
* @param size Int between 1 and 50. Default is 3.
* @returns New promise with api call for random beer list.
Expand All @@ -22,4 +24,4 @@ const searchBeerList = (query: string, isAutoComplete = false) =>

const getBeerMetaData = (params?: ApiParams) => axios.get(`${API}breweries/meta`, { params });

export { getBeer, getBeerList, getRandomBeerList, searchBeerList, getBeerMetaData };
export { getBeer, getBeerList, getRandomBeerList, searchBeerList, getBeerMetaData, getFavouriteListByIds };
22 changes: 22 additions & 0 deletions BeerApp - Senior/src/components/Map/Map.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import React, { useRef } from "react";
import { MapContainer, TileLayer } from "react-leaflet";
import "leaflet/dist/leaflet.css";

const Map = ({lat, lang}) => {
const mapRef = useRef(null);
const latitude = lat;
const longitude = lang;

return (
// Make sure you set the height and width of the map container otherwise the map won't show
<MapContainer center={[latitude, longitude]} zoom={13} ref={mapRef} style={{height: "100vh", width: "100vw"}}>
<TileLayer
attribution='&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
/>
{/* Additional map layers or components can be added here */}
</MapContainer>
);
};

export default Map;
2 changes: 1 addition & 1 deletion BeerApp - Senior/src/components/TopBar/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ const TopBar = (props: Props) => {
<MenuIcon />
</IconButton>
<Typography variant="h6" noWrap component="div">
V
BeerWiki
</Typography>
</Toolbar>
</AppBar>
Expand Down
15 changes: 9 additions & 6 deletions BeerApp - Senior/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,16 @@ import CssBaseline from '@mui/material/CssBaseline';
import { ThemeProvider } from '@emotion/react';
import { theme } from './styles/theme';
import './styles/global.css';
import { registerServiceWorker } from './registerServiceWorker';

registerServiceWorker();

const root = ReactDOM.createRoot(document.getElementById('root') as HTMLElement);
root.render(
<React.StrictMode>
<CssBaseline />
<ThemeProvider theme={theme}>
<Router />
</ThemeProvider>
</React.StrictMode>
<React.StrictMode>
<CssBaseline />
<ThemeProvider theme={theme}>
<Router />
</ThemeProvider>
</React.StrictMode>
);
15 changes: 15 additions & 0 deletions BeerApp - Senior/src/registerServiceWorker.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// registerServiceWorker.js or registerServiceWorker.ts

export const registerServiceWorker = () => {
if ('serviceWorker' in navigator) {
navigator.serviceWorker
.register('/service-worker.js')
.then((registration) => {
console.log('Service Worker registered with scope:', registration.scope);
})
.catch((error) => {
console.error('Service Worker registration failed:', error);
});
}
};

1 change: 1 addition & 0 deletions BeerApp - Senior/src/setupTests.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
import '@testing-library/jest-dom';
14 changes: 14 additions & 0 deletions BeerApp - Senior/src/utils/favoritesUtils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
const saveAsFavourite = (id: string, setFavourite: React.Dispatch<React.SetStateAction<string[]>>) => {
const favouriteList = JSON.parse(localStorage.getItem('favouriteList') || '[]');
if (favouriteList.indexOf(id) === -1) {
favouriteList.push(id);
localStorage.setItem('favouriteList', JSON.stringify(favouriteList));
setFavourite(favouriteList);
} else {
favouriteList.splice(favouriteList.indexOf(id), 1);
localStorage.setItem('favouriteList', JSON.stringify(favouriteList));
setFavourite(favouriteList);
}
};

export default saveAsFavourite;
21 changes: 21 additions & 0 deletions BeerApp - Senior/src/views/Beer/Beer.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
root {
margin: 'auto';
padding: '20px'
}
.title {
font-weight: 'bold';
font-size: '3rem';
margin-top: '10px';
}
.subtitle {
font-size: '2rem';
margin-bottom: '10px';
}
.subheading {
font-size: '1.75rem';
margin-top: '20px';
}
.cardContent {
display: 'flex';
padding: 1.5rem;
}
32 changes: 32 additions & 0 deletions BeerApp - Senior/src/views/Beer/Map.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import React, { useRef } from "react";
import { MapContainer, Marker, Popup, TileLayer } from "react-leaflet";
import "leaflet/dist/leaflet.css";

interface MapProps {
lat: number;
lang: number;
name: string;
}

const Map: React.FC<MapProps> = ({ lat, lang, name }) => {
const mapRef = useRef(null);
const latitude = lat;
const longitude = lang;
const companyName = name;

return (
<MapContainer center={[latitude, longitude]} zoom={15} ref={mapRef} style={{height: "70vh", width: "40vw"}}>
<TileLayer
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
attribution='&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
/>
<Marker position={[latitude, longitude]}>
<Popup>
{companyName}
</Popup>
</Marker>
</MapContainer>
);
};

export default Map;
9 changes: 9 additions & 0 deletions BeerApp - Senior/src/views/Beer/index.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { render } from '@testing-library/react';
import Beer from './index';

describe('Beer', () => {
test('checks the type of Beer component', () => {
render(<Beer />);
expect(typeof Beer).toBe('function');
});
});
80 changes: 62 additions & 18 deletions BeerApp - Senior/src/views/Beer/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,72 @@ import { useEffect, useState } from 'react';
import { Beer as IBeer } from '../../types';
import { fetchData } from './utils';
import { useParams } from 'react-router-dom';
import { Typography, IconButton, Paper } from '@mui/material';
import Map from './Map';
import saveAsFavourite from '../../utils/favoritesUtils';
import FavoriteIcon from '@mui/icons-material/Favorite';
import FavoriteBorderIcon from '@mui/icons-material/FavoriteBorder';
import styles from './Beer.module.css';

const Beer = () => {
const { id } = useParams();
const [beer, setBeer] = useState<IBeer>();
const { id } = useParams();
const [beer, setBeer] = useState<IBeer>();
const [favourite, setFavourite] = useState<Array<string>>([]);

// eslint-disable-next-line
useEffect(fetchData.bind(this, setBeer, id), [id]);
// eslint-disable-next-line
useEffect(fetchData.bind(this, setBeer, id), [id]);

return (
<article>
<section>
<header>
<h1>{beer?.name}</h1>
</header>
<main>
<span>
<b>Type: </b> {beer?.brewery_type}
</span>
</main>
</section>
</article>
);
useEffect(() => {
let data = JSON.parse(localStorage.getItem('favouriteList') || '[]');
setFavourite(data);
}, [id]);

const saveFavourite = (id: string) => {
saveAsFavourite(id, setFavourite);
};

return (
<Paper className={styles.root}>
{beer && (
<div className={styles.cardContent}>
<Typography variant="h3" component="h3" className={styles.title}>
{beer?.name} <IconButton onClick={saveFavourite.bind(this, beer?.id ?? "")} color="primary" size="large">
{favourite.includes(beer?.id ?? '') ? <FavoriteIcon /> : <FavoriteBorderIcon />}
</IconButton>
</Typography>
<Typography variant="h4" component="h4" className={styles.subtitle}>
Type: {beer?.brewery_type}
</Typography>
<Typography className={styles.subheading}>Website:</Typography>
<Typography variant="body2" component="p">
{beer?.website_url
? (<a href={beer?.website_url} target='_blank' rel="noreferrer">{beer?.website_url}</a>)
: ('No website available')
}
</Typography>
<Typography className={styles.subheading}>Phone:</Typography>
<Typography variant="body2" component="p">
{beer?.phone
? (<a href="tel:{beer?.phone}">{beer?.phone}</a>)
: ('No phone available')
}
</Typography>
<Typography variant="h4" component="h4" className={styles.subheading}>Location:</Typography>
<Typography variant="body2" component="p">
{beer?.street}, {beer?.postal_code}
<br />{beer?.city}, {beer?.state}
<br />{beer?.country}
</Typography>
{beer?.latitude && beer?.longitude && (
<div>
<Map lat={Number(beer.latitude)} lang={Number(beer.longitude)} name={beer.name} />
<Typography variant="h6" component="h6" className={styles.subheading}>Coordinate: {+(beer.latitude)}, {+(beer.longitude)}</Typography>
</div>
)}
</div>
)}
</Paper>
);
};

export default Beer;
4 changes: 4 additions & 0 deletions BeerApp - Senior/src/views/BeerList/BeerList.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
.buttonAlignment {
margin-left: 10px;
margin-top: 10px;
}
Loading