Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • andretol/greg
1 result
Show changes
Commits on Source (10)
Showing
with 22319 additions and 167 deletions
This diff is collapsed.
...@@ -16,7 +16,9 @@ ...@@ -16,7 +16,9 @@
"i18next-http-backend": "^1.3.1", "i18next-http-backend": "^1.3.1",
"react": "^17.0.2", "react": "^17.0.2",
"react-dom": "^17.0.2", "react-dom": "^17.0.2",
"react-helmet": "^6.1.0",
"react-i18next": "^11.11.4", "react-i18next": "^11.11.4",
"react-router-dom": "^5.3.0",
"react-scripts": "4.0.3", "react-scripts": "4.0.3",
"styled-components": "^5.3.1", "styled-components": "^5.3.1",
"typescript": "^4.4.2", "typescript": "^4.4.2",
...@@ -47,5 +49,9 @@ ...@@ -47,5 +49,9 @@
"last 1 firefox version", "last 1 firefox version",
"last 1 safari version" "last 1 safari version"
] ]
},
"devDependencies": {
"@types/react-helmet": "^6.1.2",
"@types/react-router-dom": "^5.1.8"
} }
} }
...@@ -5,5 +5,6 @@ ...@@ -5,5 +5,6 @@
}, },
"language": { "language": {
"change": "Change language to {{lang}}" "change": "Change language to {{lang}}"
} },
"loading": "Loading..."
} }
...@@ -5,5 +5,6 @@ ...@@ -5,5 +5,6 @@
}, },
"language": { "language": {
"change": "Bytt språk til {{lang}}" "change": "Bytt språk til {{lang}}"
} },
"loading": "Laster..."
} }
...@@ -5,5 +5,6 @@ ...@@ -5,5 +5,6 @@
}, },
"language": { "language": {
"change": "Bytt språk til {{lang}}" "change": "Bytt språk til {{lang}}"
} },
"loading": "Lastar..."
} }
.App {
text-align: center;
}
.App-logo {
height: 40vmin;
pointer-events: none;
}
@media (prefers-reduced-motion: no-preference) {
.App-logo {
animation: App-logo-spin infinite 20s linear;
}
}
.App-header {
background-color: #282c34;
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
font-size: calc(10px + 2vmin);
color: white;
}
.App-link {
color: #61dafb;
}
@keyframes App-logo-spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
import React from 'react'
import { render, screen } from '@testing-library/react'
import App from './App'
test('renders learn react link', () => {
render(<App />)
const linkElement = screen.getByText(/learn react/i)
expect(linkElement).toBeInTheDocument()
})
import React, { useState } from 'react'
import { useTranslation } from 'react-i18next'
import './App.css'
import { Button } from './components/button'
import { appTimezone, appVersion, appTheme } from './appConfig'
import Link from './components/link'
const App = () => {
const [apiHealth, setApiHealth] = useState('not yet')
const [didContactApi, setDidContactApi] = useState(false)
const { t, i18n } = useTranslation(['common', 'footer'])
if (!didContactApi) {
setDidContactApi(true)
fetch('http://localhost:3000/api/health/')
.then((res) => res.text())
.then((result) => {
if (result === 'OK') {
setApiHealth('yes')
} else {
setApiHealth(result)
}
})
.catch((error) => {
setApiHealth('error')
console.log(error)
})
}
return (
<div className="App">
<header className="App-header">
<Button href="https://example.com" target="_blank" rel="noopener">
Knapp
</Button>
<Button href="https://example.com" target="_blank" rel="noopener">
Rosa knapp
</Button>
<p>{t('common:test')}</p>
<p>{t('common:nested.test')}</p>
<p>{t('footer:footerInfo')}</p>
<Button
onClick={() =>
i18n.language === 'en'
? i18n.changeLanguage('nb')
: i18n.changeLanguage('en')
}
>
{t('common:language.change', {
lang: i18n.language === 'en' ? 'Norsk' : 'Engelsk',
})}
</Button>
<p>
Version {appVersion}
<br />
Timezone {appTimezone}
<br />
Theme {appTheme}
<br />
API reachable? {apiHealth}
</p>
<Link to='test@example.org' mail={true}>Mail link</Link>
<Link to='test4' external={false} underline={true} noExternalIcon={true}>Internal link</Link>
<Link to='test6' external={true} underline={false} noUnderline={true}>External link</Link>
<Link to='test5' external={false} noUnderline={true}>Another internal link</Link>
</header>
</div>
)
}
export default App
import styled from 'styled-components/macro'
const Spinner = styled.div`
position: relative;
display: inline-block;
width: 1.5rem;
height: 1.5rem;
margin-left: 0;
margin-right: 1rem;
margin-top: 0;
border: 3px solid rgba(200, 200, 200);
border-width: 3px;
border-radius: 50%;
border-top-color: rgba(50, 50, 50);
animation: spin 0.8s linear infinite;
@keyframes spin {
to {
transform: rotate(360deg);
}
}
`
export default Spinner
import styled, { DefaultTheme } from 'styled-components/macro' import styled from 'styled-components/macro'
type ButtonProps = { export const Button = styled.a`
theme: DefaultTheme
}
export const Button = styled.a<ButtonProps>`
display: inline-block; display: inline-block;
border-radius: 3px; border-radius: 3px;
padding: 0.5rem 0; padding: 0.5rem 0;
...@@ -14,8 +10,8 @@ export const Button = styled.a<ButtonProps>` ...@@ -14,8 +10,8 @@ export const Button = styled.a<ButtonProps>`
color: white; color: white;
border: 2px solid white; border: 2px solid white;
:hover { :hover {
background: ${(props) => props.theme.colors.secondary}; background: ${({ theme }) => theme.colors.secondary};
color: black; color: black;
} }
background: ${(props) => props.theme.colors.main}; background: ${({ theme }) => theme.colors.main};
` `
import React from 'react'
import { useTranslation } from 'react-i18next'
import Spinner from 'components/animations/spinner'
import styled from 'styled-components/macro'
const SpinnerWrapper = styled.div`
display: flex;
justify-content: center;
align-items: center;
`
function Loading() {
const { t } = useTranslation(['common'])
return (
<SpinnerWrapper>
<Spinner />
{t('common:loading')}
</SpinnerWrapper>
)
}
export default Loading
import Page from 'components/page/page'
export { Page }
import React from 'react'
import { Helmet } from 'react-helmet'
import styled from 'styled-components/macro'
const StyledPage = styled.main`
display: block;
`
const StyledPageHeader = styled.h2`
color: ${({ theme }) => theme.page.headerColor};
font-size: 3rem;
font-weight: bold;
margin: 0rem ${({ theme }) => theme.page.horizontalPadding} 0
${({ theme }) => theme.page.horizontalPadding};
`
interface IPage {
children: React.ReactNode
header: string
}
export default function Page(props: IPage) {
const { header, children } = props
return (
<>
<Helmet>
<title>{header}</title>
</Helmet>
<StyledPage>
<StyledPageHeader>{header}</StyledPageHeader>
{children}
</StyledPage>
</>
)
}
...@@ -3,6 +3,7 @@ import { createGlobalStyle } from 'styled-components/macro' ...@@ -3,6 +3,7 @@ import { createGlobalStyle } from 'styled-components/macro'
const GlobalStyle = createGlobalStyle` const GlobalStyle = createGlobalStyle`
body { body {
margin: 0; margin: 0;
min-height: 100vh;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif; 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
-webkit-font-smoothing: antialiased; -webkit-font-smoothing: antialiased;
...@@ -13,6 +14,10 @@ const GlobalStyle = createGlobalStyle` ...@@ -13,6 +14,10 @@ const GlobalStyle = createGlobalStyle`
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
monospace; monospace;
} }
#root {
min-height: 100vh;
}
` `
export default GlobalStyle export default GlobalStyle
import React, { Suspense } from 'react' import React, { Suspense } from 'react'
import ReactDOM from 'react-dom' import ReactDOM from 'react-dom'
import { ThemeProvider } from 'styled-components/macro' import { ThemeProvider } from 'styled-components/macro'
import { BrowserRouter as Router } from 'react-router-dom'
import 'i18n' import 'i18n'
import getCurrentTheme from 'theme'
import getTheme from 'themes'
import GlobalStyle from 'globalStyles' import GlobalStyle from 'globalStyles'
import App from './App' import App from 'routes'
import reportWebVitals from './reportWebVitals' import reportWebVitals from './reportWebVitals'
import Loading from 'components/loading'
function appRoot() { function appRoot() {
return ( return (
<> <React.StrictMode>
<React.StrictMode> <Router>
<GlobalStyle /> <GlobalStyle />
<Suspense fallback="loading"> <Suspense fallback={<Loading />}>
<ThemeProvider theme={getCurrentTheme()}> <ThemeProvider theme={getTheme()}>
<App /> <App />
</ThemeProvider> </ThemeProvider>
</Suspense> </Suspense>
</React.StrictMode> </Router>
</> </React.StrictMode>
) )
} }
......
import React from 'react'
import styled from 'styled-components/macro'
// Placeholder footer component
const StyledFooter = styled.footer`
background: ${({ theme }) => theme.footer.backgroundColor};
padding: 4rem 0;
margin-top: auto;
`
const FooterWrapper = styled.div`
background: ${({ theme }) => theme.footer.backgroundColor};
color: white;
height: fit-content;
max-width: ${({ theme }) => theme.appMaxWidth};
margin: 0 auto;
padding: 0rem ${({ theme }) => theme.horizontalPadding};
`
export default function Footer() {
return (
<StyledFooter>
<FooterWrapper>Footer 123</FooterWrapper>
</StyledFooter>
)
}
import React from 'react'
import styled from 'styled-components/macro'
// Placeholder header component!
const MainWrapper = styled.div`
background-color: green;
`
const Main = styled.div`
margin: 0 auto;
max-width: ${({ theme }) => theme.maxWidth};
height: ${({ theme }) => theme.header.height};
padding: 2.5rem ${({ theme }) => theme.horizontalPadding} 3rem
${({ theme }) => theme.horizontalPadding};
`
const MainRow = styled.div`
display: flex;
justify-content: space-between;
`
const PageTitle = styled.div`
color: blue;
`
const H2 = styled.h2`
font-size: 2.8rem;
line-height: 4.5rem;
`
export default function Header() {
return (
<header>
<MainWrapper>
<Main>
<MainRow>
<PageTitle>
<H2>Greg!</H2>
</PageTitle>
</MainRow>
</Main>
</MainWrapper>
</header>
)
}
import React from 'react'
import { Page } from 'components/page'
export default function NotFound() {
return (
<Page header="404 - Not found">
<h2> 404 - Not found</h2>
</Page>
)
}
import React, { useState } from 'react'
import { Page } from 'components/page'
import { appTimezone, appVersion, appTheme } from 'appConfig'
export default function FrontPage() {
const [apiHealth, setApiHealth] = useState('not yet')
const [didContactApi, setDidContactApi] = useState(false)
if (!didContactApi) {
setDidContactApi(true)
fetch('http://localhost:3000/api/health/')
.then((res) => res.text())
.then((result) => {
if (result === 'OK') {
setApiHealth('yes')
} else {
setApiHealth(result)
}
})
.catch((error) => {
setApiHealth('error')
console.log(error)
})
}
return (
<Page header="Greg main page">
Version {appVersion}
<br />
Timezone {appTimezone}
<br />
Theme {appTheme}
<br />
API reachable? {apiHealth}
</Page>
)
}
import React from 'react'
import { Switch, Route } from 'react-router-dom'
import styled from 'styled-components/macro'
import Sponsor from 'routes/sponsor'
import Register from 'routes/register'
import FrontPage from 'routes/frontpage'
import Footer from 'routes/components/footer'
import Header from 'routes/components/header'
import NotFound from 'routes/components/notFound'
const AppWrapper = styled.div`
display: flex;
flex-direction: column;
font-size: 1.6rem;
min-height: 100vh;
margin-top: auto;
`
export default function App() {
return (
<AppWrapper>
<Header />
<Switch>
<Route exact path="/">
<FrontPage />
</Route>
<Route path="/sponsor">
<Sponsor />
</Route>
<Route path="/register">
<Register />
</Route>
<Route>
<NotFound />
</Route>
</Switch>
<Footer />
</AppWrapper>
)
}