Added support for categories

This commit is contained in:
Bastian Meissner 2020-06-26 15:24:37 +02:00
parent d2b35f7339
commit 9c372553f9
6 changed files with 106 additions and 63 deletions

View file

@ -12,6 +12,7 @@ import selectedTheme from './components/themeManager';
const GlobalStyle = createGlobalStyle`
body {
background-color: ${selectedTheme.backgroundColor};
font-family: Roboto, sans-serif;
}
`;

View file

@ -7,10 +7,11 @@ import selectedTheme from './themeManager';
import {
handleResponse,
Headline,
SubHeadline,
ListContainer,
ItemList,
Item,
ErrorMessage
ErrorMessage,
} from './elements';
const IconContainer = styled.div`
@ -46,9 +47,13 @@ const Description = styled.p`
color: ${selectedTheme.accentColor};
`;
const CategoryContainer = styled.div`
padding: 1rem 0;
`;
const App = styled.div`
display: flex;
flex-basis: 25%;
flex: auto 25%;
padding: 1rem;
`;
@ -59,11 +64,11 @@ const useAppData = () => {
? fetch('/data/apps.json').then(handleResponse)
: import('./data/apps.json')
)
.then(jsonResponse => {
.then((jsonResponse) => {
setAppData({ ...jsonResponse, error: false });
})
.catch(error => {
setAppData({ apps: [], error: error.message });
.catch((error) => {
setAppData({ categories: [], apps: [], error: error.message });
});
}, []);
@ -75,17 +80,52 @@ const useAppData = () => {
const AppList = () => {
const {
appData: { apps, error }
appData: { categories, apps, error },
} = useAppData();
return (
<ListContainer>
<Headline>Applications</Headline>
{categories && (
<CategoryContainer>
{categories.map((category, idx) => (
<>
<SubHeadline key={[category.name, idx].join('')}>
{category.name}
</SubHeadline>
<ItemList>
{category.items.map((app, idx) => (
<Item key={[app.name, idx].join('')}>
<App>
<IconContainer>
<MaterialIcon
icon={app.icon}
color={
selectedTheme.mainColor
}
/>
</IconContainer>
<DetailsContainer>
<Link href={app.URL}>
{app.name}
</Link>
<Description>
{app.displayURL}
</Description>
</DetailsContainer>
</App>
</Item>
))}
</ItemList>
</>
))}
</CategoryContainer>
)}
<ItemList>
{error && <ErrorMessage>{error}</ErrorMessage>}
{apps.map((app, idx) => {
const { name } = app;
return (
<Item key={[name, idx].join('')}>
{apps.map((app, idx) => (
<Item key={[app.name, idx].join('')}>
<App>
<IconContainer>
<MaterialIcon
@ -99,8 +139,7 @@ const AppList = () => {
</DetailsContainer>
</App>
</Item>
);
})}
))}
</ItemList>
</ListContainer>
);

View file

@ -8,7 +8,7 @@ import {
ListContainer,
ItemList,
Item,
ErrorMessage
ErrorMessage,
} from './elements';
const Group = styled.h4`
@ -23,7 +23,7 @@ const BookmarkGroup = styled.div`
display: flex;
flex-direction: column;
flex: 2 1 auto;
padding: 1rem 0 1rem 0;
padding: 1rem 0;
`;
const Bookmark = styled.a`
@ -31,7 +31,7 @@ const Bookmark = styled.a`
font-weight: 400;
text-decoration: none;
color: ${selectedTheme.accentColor};
padding: 10px 0 0 0;
padding-top: 10px;
font-size: 14px;
&:hover {
@ -42,7 +42,7 @@ const Bookmark = styled.a`
const useBookmarkData = () => {
const [bookmarkData, setBookmarkData] = useState({
groups: [],
error: false
error: false,
});
const fetchBookmarkData = useCallback(() => {
@ -50,10 +50,10 @@ const useBookmarkData = () => {
? fetch('/data/bookmarks.json').then(handleResponse)
: import('./data/bookmarks.json')
)
.then(jsonResponse => {
.then((jsonResponse) => {
setBookmarkData({ ...jsonResponse, error: false });
})
.catch(error => {
.catch((error) => {
setBookmarkData({ groups: [], error: error.message });
});
}, []);
@ -66,7 +66,7 @@ const useBookmarkData = () => {
const BookmarkList = () => {
const {
bookmarkData: { groups, error }
bookmarkData: { groups, error },
} = useBookmarkData();
return (
<ListContainer>

View file

@ -5,7 +5,7 @@ import MaterialIcon from 'material-icons-react';
// File for elements that are/can be reused across the entire site.
export const handleResponse = response => {
export const handleResponse = (response) => {
if (response.ok) {
return response.json();
}
@ -13,12 +13,11 @@ export const handleResponse = response => {
};
export const ListContainer = styled.div`
padding: 2rem 0 2rem 0;
padding: 2rem 0;
`;
export const Headline = styled.h3`
display: inline-block;
font-family: Roboto, sans-serif;
font-weight: 900;
text-transform: uppercase;
margin: 0px;
@ -26,6 +25,15 @@ export const Headline = styled.h3`
color: ${selectedTheme.mainColor};
`;
export const SubHeadline = styled.h4`
display: inline-block;
font-weight: 700;
text-transform: uppercase;
margin: 0px;
font-size: 1.5rem;
color: ${selectedTheme.mainColor};
`;
export const ItemList = styled.ul`
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
@ -41,7 +49,6 @@ export const Item = styled.li`
`;
export const Button = styled.button`
font-family: Roboto, sans-serif;
text-transform: uppercase;
font-weight: 400;
border: 1px solid ${selectedTheme.mainColor};
@ -75,7 +82,7 @@ export const ErrorMessage = styled.p`
color: red;
`;
export const IconButton = props => {
export const IconButton = (props) => {
if (
props.icon &&
props.icon !== '' &&

View file

@ -4,19 +4,17 @@ import styled from 'styled-components';
import selectedTheme from './themeManager';
const GreeterContainer = styled.div`
padding: 2rem 0 2rem 0;
padding: 2rem 0;
`;
const GreetText = styled.h1`
font-family: Roboto, sans-serif;
font-weight: 900;
font-size: 45px;
margin: 0.5rem 0 0.5rem 0;
margin: 0.5rem 0;
color: ${selectedTheme.mainColor};
`;
const DateText = styled.h3`
font-family: Roboto, sans-serif;
font-weight: 400;
font-size: 15px;
text-transform: uppercase;
@ -39,7 +37,7 @@ const getGreeting = () => {
}
};
const getExtension = day => {
const getExtension = (day) => {
let extension = '';
if ((day > 4 && day <= 20) || (day > 20 && day % 10 >= 4)) {
@ -67,7 +65,7 @@ const monthNames = [
'September',
'October',
'November',
'December'
'December',
];
const weekDayNames = [
@ -77,7 +75,7 @@ const weekDayNames = [
'Wednesday',
'Thursday',
'Friday',
'Saturday'
'Saturday',
];
const getDateString = () => {

View file

@ -11,11 +11,11 @@ import {
Button,
IconButton,
ErrorMessage,
Headline as hl
Headline as hl,
} from './elements';
const Headline = styled(hl)`
padding: 0.5rem 0 0.5rem 0;
padding: 0.5rem 0;
`;
const Modal = styled.div`
@ -60,9 +60,8 @@ const HeadCell = styled.th`
`;
const SelectorStyle = {
control: provided => ({
control: (provided) => ({
...provided,
fontFamily: 'Roboto, sans-serif',
fontWeight: '500',
color: selectedTheme.mainColor,
textTransform: 'uppercase',
@ -72,19 +71,18 @@ const SelectorStyle = {
border: '1px solid ' + selectedTheme.mainColor,
boxShadow: 0,
'&:hover': {
border: '1px solid ' + selectedTheme.mainColor
}
border: '1px solid ' + selectedTheme.mainColor,
},
}),
menu: provided => ({
menu: (provided) => ({
...provided,
backgroundColor: selectedTheme.backgroundColor,
border: '1px solid ' + selectedTheme.mainColor,
borderRadius: '0px',
boxShadow: 0
boxShadow: 0,
}),
option: provided => ({
option: (provided) => ({
...provided,
fontFamily: 'Roboto, sans-serif',
fontWeight: '500',
color: selectedTheme.mainColor,
textTransform: 'uppercase',
@ -93,15 +91,15 @@ const SelectorStyle = {
backgroundColor: selectedTheme.backgroundColor,
'&:hover': {
backgroundColor: selectedTheme.mainColor,
color: selectedTheme.backgroundColor
}
color: selectedTheme.backgroundColor,
},
}),
singleValue: provided => {
singleValue: (provided) => {
return {
...provided,
color: selectedTheme.mainColor
color: selectedTheme.mainColor,
};
}
},
};
const useThemeData = () => {
@ -112,10 +110,10 @@ const useThemeData = () => {
? fetch('/data/themes.json').then(handleResponse)
: import('./data/themes.json')
)
.then(jsonResponse => {
.then((jsonResponse) => {
setThemeData({ ...jsonResponse, error: false });
})
.catch(error => {
.catch((error) => {
setThemeData({ themes: [], error: error.message });
});
}, []);
@ -131,7 +129,7 @@ const SettingsModal = () => {
const [newTheme, setNewTheme] = useState();
const {
themeData: { themes, error }
themeData: { themes, error },
} = useThemeData();
return (
@ -152,7 +150,7 @@ const SettingsModal = () => {
<Select
options={themes}
defaultValue={selectedTheme}
onChange={e => {
onChange={(e) => {
setNewTheme(e);
}}
styles={SelectorStyle}