chore: resize writing area, add name to navbar
This commit is contained in:
56
src/App.js
56
src/App.js
@@ -1,18 +1,20 @@
|
|||||||
import React, { Component } from "react";
|
import React, { Component } from "react"
|
||||||
import { BrowserRouter as Router, Route } from "react-router-dom";
|
import { BrowserRouter as Router, Route } from "react-router-dom"
|
||||||
import styled from "@emotion/styled";
|
import styled from "@emotion/styled"
|
||||||
import { ThemeProvider } from "emotion-theming";
|
import { ThemeProvider } from "emotion-theming"
|
||||||
|
|
||||||
import theme from "./styles/theme";
|
import { SIZES } from "./styles/constants"
|
||||||
import Navbar from "./components/Navbar";
|
|
||||||
import Day from "./components/screens/Day";
|
|
||||||
import Month from "./components/screens/Month";
|
|
||||||
import Year from "./components/screens/Year";
|
|
||||||
import User from "./components/screens/User";
|
|
||||||
import Login from "./components/screens/Login";
|
|
||||||
import Register from "./components/screens/Register";
|
|
||||||
|
|
||||||
import { withAuthentication } from "./components/session";
|
import theme from "./styles/theme"
|
||||||
|
import Navbar from "./components/Navbar"
|
||||||
|
import Day from "./components/screens/Day"
|
||||||
|
import Month from "./components/screens/Month"
|
||||||
|
import Year from "./components/screens/Year"
|
||||||
|
import User from "./components/screens/User"
|
||||||
|
import Login from "./components/screens/Login"
|
||||||
|
import Register from "./components/screens/Register"
|
||||||
|
|
||||||
|
import { withAuthentication } from "./components/session"
|
||||||
|
|
||||||
const RouteLayout = styled.div`
|
const RouteLayout = styled.div`
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -20,32 +22,32 @@ const RouteLayout = styled.div`
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
padding: 0 10px;
|
padding: 0 10px;
|
||||||
max-width: 720px;
|
max-width: ${SIZES.maxWidth};
|
||||||
min-height: calc(100vh - 60px);
|
min-height: calc(100vh - 60px);
|
||||||
background-color: ${props => props.theme.colors.bodyBackground};
|
background-color: ${props => props.theme.colors.bodyBackground};
|
||||||
`;
|
`
|
||||||
|
|
||||||
class App extends Component {
|
class App extends Component {
|
||||||
state = {
|
state = {
|
||||||
authUser: JSON.parse(localStorage.getItem("authUser")),
|
authUser: JSON.parse(localStorage.getItem("authUser")),
|
||||||
selectedTheme: "LIGHT"
|
selectedTheme: "LIGHT",
|
||||||
};
|
}
|
||||||
|
|
||||||
onChangeTheme = () => {
|
onChangeTheme = () => {
|
||||||
const { selectedTheme } = this.state;
|
const { selectedTheme } = this.state
|
||||||
const root = document.documentElement;
|
const root = document.documentElement
|
||||||
const newTheme = selectedTheme === "LIGHT" ? "DARK" : "LIGHT";
|
const newTheme = selectedTheme === "LIGHT" ? "DARK" : "LIGHT"
|
||||||
root.style.setProperty(
|
root.style.setProperty(
|
||||||
"background-color",
|
"background-color",
|
||||||
theme[newTheme].colors.bodyBackground
|
theme[newTheme].colors.bodyBackground
|
||||||
);
|
)
|
||||||
this.setState({ selectedTheme: newTheme });
|
this.setState({ selectedTheme: newTheme })
|
||||||
};
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { selectedTheme } = this.state;
|
const { selectedTheme } = this.state
|
||||||
|
|
||||||
const currentTheme = theme[selectedTheme];
|
const currentTheme = theme[selectedTheme]
|
||||||
return (
|
return (
|
||||||
<ThemeProvider theme={currentTheme}>
|
<ThemeProvider theme={currentTheme}>
|
||||||
<Router>
|
<Router>
|
||||||
@@ -68,8 +70,8 @@ class App extends Component {
|
|||||||
</RouteLayout>
|
</RouteLayout>
|
||||||
</Router>
|
</Router>
|
||||||
</ThemeProvider>
|
</ThemeProvider>
|
||||||
);
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default withAuthentication(App);
|
export default withAuthentication(App)
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import React from 'react';
|
import React from "react"
|
||||||
import ReactDOM from 'react-dom';
|
import ReactDOM from "react-dom"
|
||||||
import App from './App';
|
import App from "./App"
|
||||||
|
|
||||||
it('renders without crashing', () => {
|
it("renders without crashing", () => {
|
||||||
const div = document.createElement('div');
|
const div = document.createElement("div")
|
||||||
ReactDOM.render(<App />, div);
|
ReactDOM.render(<App />, div)
|
||||||
ReactDOM.unmountComponentAtNode(div);
|
ReactDOM.unmountComponentAtNode(div)
|
||||||
});
|
})
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ const Icon = ({ name, ...rest }) => (
|
|||||||
{name === "ChevronLeft" && <ChevronLeft />}
|
{name === "ChevronLeft" && <ChevronLeft />}
|
||||||
{name === "ChevronRight" && <ChevronRight />}
|
{name === "ChevronRight" && <ChevronRight />}
|
||||||
{name === "Circle" && <Circle />}
|
{name === "Circle" && <Circle />}
|
||||||
|
{name === "Edit2" && <Edit2 />}
|
||||||
{name === "Moon" && <Moon />}
|
{name === "Moon" && <Moon />}
|
||||||
{name === "Sun" && <Sun />}
|
{name === "Sun" && <Sun />}
|
||||||
{name === "User" && <User />}
|
{name === "User" && <User />}
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
import Icon from "./Icon";
|
import Icon from "./Icon"
|
||||||
export default Icon;
|
export default Icon
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import React from "react";
|
import React from "react"
|
||||||
|
|
||||||
const Logo = ({ color }) => {
|
const Logo = ({ color }) => {
|
||||||
return (
|
return (
|
||||||
@@ -123,7 +123,7 @@ const Logo = ({ color }) => {
|
|||||||
</clipPath>
|
</clipPath>
|
||||||
</defs>
|
</defs>
|
||||||
</svg>
|
</svg>
|
||||||
);
|
)
|
||||||
};
|
}
|
||||||
|
|
||||||
export default Logo;
|
export default Logo
|
||||||
|
|||||||
@@ -1,38 +1,49 @@
|
|||||||
import React from "react";
|
import React from "react"
|
||||||
import { Link } from "react-router-dom";
|
import { Link } from "react-router-dom"
|
||||||
import styled from "@emotion/styled";
|
import styled from "@emotion/styled"
|
||||||
import { compose } from "recompose";
|
import { compose } from "recompose"
|
||||||
import { withTheme } from "emotion-theming";
|
import { withTheme } from "emotion-theming"
|
||||||
|
|
||||||
import { todayUrl, yearUrl } from "../../utils/date";
|
import { SIZES } from "../../styles/constants"
|
||||||
|
import { todayUrl, yearUrl } from "../../utils/date"
|
||||||
|
|
||||||
import Logo from "../Logo";
|
import Logo from "../Logo"
|
||||||
import Icon from "../Icon";
|
import Icon from "../Icon"
|
||||||
import { withAuthentication } from "../session";
|
import { withAuthentication } from "../session"
|
||||||
|
|
||||||
const Header = styled.div`
|
const Header = styled.div`
|
||||||
background-color: ${props => props.theme.colors.headerBackground};
|
background-color: ${props => props.theme.colors.headerBackground};
|
||||||
height: 60px;
|
height: 60px;
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-areas: "... nav ...";
|
grid-template-areas: "... nav ...";
|
||||||
grid-template-columns: 1fr minmax(240px, 720px) 1fr;
|
grid-template-columns: 1fr minmax(240px, ${SIZES.maxWidth}) 1fr;
|
||||||
grid-gap: 10px;
|
grid-gap: 10px;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
border-width: 1px;
|
border-width: 1px;
|
||||||
border-color: ${props => props.theme.colors.quarternary};
|
border-color: ${props => props.theme.colors.quarternary};
|
||||||
border-style: solid;
|
border-style: solid;
|
||||||
`;
|
`
|
||||||
const Nav = styled.div`
|
const Nav = styled.div`
|
||||||
grid-area: nav;
|
grid-area: nav;
|
||||||
max-width: 720px;
|
max-width: ${SIZES.maxWidth};
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-content: center;
|
align-content: center;
|
||||||
`;
|
`
|
||||||
const LogoSection = styled.div`
|
const LogoSection = styled.div`
|
||||||
width: 40px;
|
height: 40px;
|
||||||
`;
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
font-family: "Montserrat", sans-serif;
|
||||||
|
font-weight: 700;
|
||||||
|
font-size: 18px;
|
||||||
|
`
|
||||||
|
const LogoText = styled.span`
|
||||||
|
color: ${props => props.color};
|
||||||
|
margin-left: 5px;
|
||||||
|
`
|
||||||
const NavIcons = styled.div`
|
const NavIcons = styled.div`
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
@@ -40,27 +51,29 @@ const NavIcons = styled.div`
|
|||||||
* + * {
|
* + * {
|
||||||
margin-left: 10px;
|
margin-left: 10px;
|
||||||
}
|
}
|
||||||
`;
|
`
|
||||||
|
|
||||||
const Navbar = ({ authUser, theme, toggleTheme }) => (
|
const Navbar = ({ authUser, theme, toggleTheme }) => (
|
||||||
<Header>
|
<Header>
|
||||||
<Nav>
|
<Nav>
|
||||||
<LogoSection>
|
<LogoSection>
|
||||||
<Logo color={theme.colors.logo} />
|
<Logo color={theme.colors.logo} />
|
||||||
|
<LogoText color={theme.colors.primary}>SOL</LogoText>{" "}
|
||||||
|
<LogoText color={theme.colors.secondary}>JOURNAL</LogoText>
|
||||||
</LogoSection>
|
</LogoSection>
|
||||||
<NavIcons>
|
<NavIcons>
|
||||||
|
{authUser ? (
|
||||||
|
<React.Fragment>
|
||||||
|
<Link to={todayUrl()}>
|
||||||
|
<Icon name="Edit2" />
|
||||||
|
</Link>
|
||||||
|
<Link to={yearUrl()}>
|
||||||
|
<Icon name="Calendar" />
|
||||||
|
</Link>
|
||||||
<Icon
|
<Icon
|
||||||
onClick={() => toggleTheme()}
|
onClick={() => toggleTheme()}
|
||||||
name={theme.name === "Dark" ? "Sun" : "Moon"}
|
name={theme.name === "Dark" ? "Sun" : "Moon"}
|
||||||
/>
|
/>
|
||||||
{authUser ? (
|
|
||||||
<React.Fragment>
|
|
||||||
<Link to={yearUrl()}>
|
|
||||||
<Icon name="Calendar" />
|
|
||||||
</Link>
|
|
||||||
<Link to={todayUrl()}>
|
|
||||||
<Icon name="Book" />
|
|
||||||
</Link>
|
|
||||||
<Link to={"/user"}>
|
<Link to={"/user"}>
|
||||||
<Icon name="User" />
|
<Icon name="User" />
|
||||||
</Link>
|
</Link>
|
||||||
@@ -75,9 +88,9 @@ const Navbar = ({ authUser, theme, toggleTheme }) => (
|
|||||||
</NavIcons>
|
</NavIcons>
|
||||||
</Nav>
|
</Nav>
|
||||||
</Header>
|
</Header>
|
||||||
);
|
)
|
||||||
|
|
||||||
export default compose(
|
export default compose(
|
||||||
withAuthentication,
|
withAuthentication,
|
||||||
withTheme
|
withTheme
|
||||||
)(Navbar);
|
)(Navbar)
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
import Navbar from "./Navbar";
|
import Navbar from "./Navbar"
|
||||||
export default Navbar;
|
export default Navbar
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import React from "react";
|
import React from "react"
|
||||||
import styled from "@emotion/styled";
|
import styled from "@emotion/styled"
|
||||||
import { withTheme } from "emotion-theming";
|
import { withTheme } from "emotion-theming"
|
||||||
import { Link } from "react-router-dom";
|
import { Link } from "react-router-dom"
|
||||||
|
|
||||||
import { SIZES } from "../../styles/constants";
|
import { SIZES } from "../../styles/constants"
|
||||||
import Icon from "../Icon";
|
import Icon from "../Icon"
|
||||||
|
|
||||||
const SeekHeader = styled.header`
|
const SeekHeader = styled.header`
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -14,17 +14,17 @@ const SeekHeader = styled.header`
|
|||||||
border-bottom-width: 1px;
|
border-bottom-width: 1px;
|
||||||
border-bottom-style: solid;
|
border-bottom-style: solid;
|
||||||
border-color: ${props => props.theme.colors.quarternary};
|
border-color: ${props => props.theme.colors.quarternary};
|
||||||
`;
|
`
|
||||||
const SeekH1 = styled.h1`
|
const SeekH1 = styled.h1`
|
||||||
display: block;
|
display: block;
|
||||||
font-size: ${SIZES.normal};
|
font-size: ${SIZES.normal};
|
||||||
color: ${props => props.theme.colors.secondary};
|
color: ${props => props.theme.colors.secondary};
|
||||||
`;
|
`
|
||||||
const SeekArrows = styled.div`
|
const SeekArrows = styled.div`
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: auto auto;
|
grid-template-columns: auto auto;
|
||||||
grid-gap: 10px;
|
grid-gap: 10px;
|
||||||
`;
|
`
|
||||||
|
|
||||||
const Seek = ({ title = "", prev = "", next = "", disableNext, theme }) => (
|
const Seek = ({ title = "", prev = "", next = "", disableNext, theme }) => (
|
||||||
<SeekHeader>
|
<SeekHeader>
|
||||||
@@ -38,7 +38,7 @@ const Seek = ({ title = "", prev = "", next = "", disableNext, theme }) => (
|
|||||||
disabled={disableNext}
|
disabled={disableNext}
|
||||||
name="ChevronRight"
|
name="ChevronRight"
|
||||||
style={{
|
style={{
|
||||||
color: disableNext ? theme.colors.hover : theme.colors.secondary
|
color: disableNext ? theme.colors.hover : theme.colors.secondary,
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
@@ -47,13 +47,13 @@ const Seek = ({ title = "", prev = "", next = "", disableNext, theme }) => (
|
|||||||
disabled={disableNext}
|
disabled={disableNext}
|
||||||
name="ChevronRight"
|
name="ChevronRight"
|
||||||
style={{
|
style={{
|
||||||
color: disableNext ? theme.colors.hover : theme.colors.secondary
|
color: disableNext ? theme.colors.hover : theme.colors.secondary,
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</Link>
|
</Link>
|
||||||
)}
|
)}
|
||||||
</SeekArrows>
|
</SeekArrows>
|
||||||
</SeekHeader>
|
</SeekHeader>
|
||||||
);
|
)
|
||||||
|
|
||||||
export default withTheme(Seek);
|
export default withTheme(Seek)
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
import Seek from "./Seek";
|
import Seek from "./Seek"
|
||||||
export default Seek;
|
export default Seek
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
import React from "react";
|
import React from "react"
|
||||||
|
|
||||||
import { withFirebase } from "../firebase";
|
import { withFirebase } from "../firebase"
|
||||||
|
|
||||||
const SignOutButton = ({ firebase }) => (
|
const SignOutButton = ({ firebase }) => (
|
||||||
<button type="button" onClick={firebase.doSignOut}>
|
<button type="button" onClick={firebase.doSignOut}>
|
||||||
Sign Out
|
Sign Out
|
||||||
</button>
|
</button>
|
||||||
);
|
)
|
||||||
|
|
||||||
export default withFirebase(SignOutButton);
|
export default withFirebase(SignOutButton)
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
import SignOut from "./SignOut";
|
import SignOut from "./SignOut"
|
||||||
export default SignOut;
|
export default SignOut
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
import React from "react";
|
import React from "react"
|
||||||
|
|
||||||
const FirebaseContext = React.createContext(null);
|
const FirebaseContext = React.createContext(null)
|
||||||
|
|
||||||
export const withFirebase = Component => props => (
|
export const withFirebase = Component => props => (
|
||||||
<FirebaseContext.Consumer>
|
<FirebaseContext.Consumer>
|
||||||
{firebase => <Component {...props} firebase={firebase} />}
|
{firebase => <Component {...props} firebase={firebase} />}
|
||||||
</FirebaseContext.Consumer>
|
</FirebaseContext.Consumer>
|
||||||
);
|
)
|
||||||
|
|
||||||
export default FirebaseContext;
|
export default FirebaseContext
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import app from "firebase/app";
|
import app from "firebase/app"
|
||||||
import "firebase/auth";
|
import "firebase/auth"
|
||||||
import "firebase/firestore";
|
import "firebase/firestore"
|
||||||
|
|
||||||
const config = {
|
const config = {
|
||||||
apiKey: process.env.REACT_APP_FIREBASE_API_KEY,
|
apiKey: process.env.REACT_APP_FIREBASE_API_KEY,
|
||||||
@@ -8,43 +8,43 @@ const config = {
|
|||||||
databaseURL: process.env.REACT_APP_DEV_DATABASE_URL,
|
databaseURL: process.env.REACT_APP_DEV_DATABASE_URL,
|
||||||
projectId: process.env.REACT_APP_DEV_PROJECT_ID,
|
projectId: process.env.REACT_APP_DEV_PROJECT_ID,
|
||||||
storageBucket: process.env.REACT_APP_DEV_STORAGE_BUCKET,
|
storageBucket: process.env.REACT_APP_DEV_STORAGE_BUCKET,
|
||||||
messagingSenderId: process.env.REACT_APP_DEV_MESSAGING_SENDER_ID
|
messagingSenderId: process.env.REACT_APP_DEV_MESSAGING_SENDER_ID,
|
||||||
};
|
}
|
||||||
|
|
||||||
class Firebase {
|
class Firebase {
|
||||||
constructor() {
|
constructor() {
|
||||||
app.initializeApp(config);
|
app.initializeApp(config)
|
||||||
this.auth = app.auth();
|
this.auth = app.auth()
|
||||||
this.db = app.firestore();
|
this.db = app.firestore()
|
||||||
app
|
app
|
||||||
.firestore()
|
.firestore()
|
||||||
.enablePersistence()
|
.enablePersistence()
|
||||||
.catch(function(err) {
|
.catch(function(err) {
|
||||||
if (err.code === "failed-precondition") {
|
if (err.code === "failed-precondition") {
|
||||||
console.error("firestore won't work offline with multiple tabs open");
|
console.error("firestore won't work offline with multiple tabs open")
|
||||||
} else if (err.code === "unimplemented") {
|
} else if (err.code === "unimplemented") {
|
||||||
console.error(
|
console.error(
|
||||||
"current browser can't take advantage of firestore offline"
|
"current browser can't take advantage of firestore offline"
|
||||||
);
|
)
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Auth
|
// Auth
|
||||||
doCreateUserWithEmailAndPassword = (email, password) =>
|
doCreateUserWithEmailAndPassword = (email, password) =>
|
||||||
this.auth.createUserWithEmailAndPassword(email, password);
|
this.auth.createUserWithEmailAndPassword(email, password)
|
||||||
|
|
||||||
doSignInWithEmailAndPassword = (email, password) =>
|
doSignInWithEmailAndPassword = (email, password) =>
|
||||||
this.auth.signInWithEmailAndPassword(email, password);
|
this.auth.signInWithEmailAndPassword(email, password)
|
||||||
|
|
||||||
doSignOut = () => {
|
doSignOut = () => {
|
||||||
this.auth.signOut();
|
this.auth.signOut()
|
||||||
window.location.replace("/login");
|
window.location.replace("/login")
|
||||||
};
|
}
|
||||||
|
|
||||||
doPasswordReset = email => this.auth.sendPasswordResetEmail(email);
|
doPasswordReset = email => this.auth.sendPasswordResetEmail(email)
|
||||||
|
|
||||||
doPasswordUpdate = password => this.auth.currentUser.updatePassword(password);
|
doPasswordUpdate = password => this.auth.currentUser.updatePassword(password)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Firebase;
|
export default Firebase
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import FirebaseContext, { withFirebase } from "./context";
|
import FirebaseContext, { withFirebase } from "./context"
|
||||||
import Firebase from "./fire";
|
import Firebase from "./fire"
|
||||||
|
|
||||||
export default Firebase;
|
export default Firebase
|
||||||
|
|
||||||
export { FirebaseContext, withFirebase };
|
export { FirebaseContext, withFirebase }
|
||||||
|
|||||||
@@ -1,23 +1,23 @@
|
|||||||
import React, { Component } from "react";
|
import React, { Component } from "react"
|
||||||
import styled from "@emotion/styled";
|
import styled from "@emotion/styled"
|
||||||
import { compose } from "recompose";
|
import { compose } from "recompose"
|
||||||
import { withRouter } from "react-router-dom";
|
import { withRouter } from "react-router-dom"
|
||||||
import { withTheme } from "emotion-theming";
|
import { withTheme } from "emotion-theming"
|
||||||
import { withFirebase } from "../../firebase";
|
import { withFirebase } from "../../firebase"
|
||||||
import { withAuthentication } from "../../session";
|
import { withAuthentication } from "../../session"
|
||||||
import { addDays, subDays, format, isAfter, startOfYesterday } from "date-fns";
|
import { addDays, subDays, format, isAfter, startOfYesterday } from "date-fns"
|
||||||
import { BeatLoader } from "react-spinners";
|
import { BeatLoader } from "react-spinners"
|
||||||
|
|
||||||
import { SIZES } from "../../../styles/constants";
|
import { SIZES } from "../../../styles/constants"
|
||||||
|
|
||||||
import Seek from "../../Seek";
|
import Seek from "../../Seek"
|
||||||
|
|
||||||
const JournalHeading = styled.h2`
|
const JournalHeading = styled.h2`
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
font-size: ${SIZES.tiny};
|
font-size: ${SIZES.tiny};
|
||||||
color: ${props => props.theme.colors.secondary};
|
color: ${props => props.theme.colors.secondary};
|
||||||
margin-top: ${SIZES.medium};
|
margin-top: ${SIZES.medium};
|
||||||
`;
|
`
|
||||||
const JournalEntryArea = styled.textarea`
|
const JournalEntryArea = styled.textarea`
|
||||||
font-family: sans-serif;
|
font-family: sans-serif;
|
||||||
flex-grow: 0.8;
|
flex-grow: 0.8;
|
||||||
@@ -42,60 +42,60 @@ const JournalEntryArea = styled.textarea`
|
|||||||
box-shadow: 0 0 0 8px ${props => props.theme.colors.bodyBackground},
|
box-shadow: 0 0 0 8px ${props => props.theme.colors.bodyBackground},
|
||||||
0 0 0 10px ${props => props.theme.colors.hover};
|
0 0 0 10px ${props => props.theme.colors.hover};
|
||||||
}
|
}
|
||||||
`;
|
`
|
||||||
|
|
||||||
const AUTOSAVE_DELAY = 2000;
|
const AUTOSAVE_DELAY = 2000
|
||||||
|
|
||||||
class Day extends Component {
|
class Day extends Component {
|
||||||
state = {
|
state = {
|
||||||
text: "",
|
text: "",
|
||||||
loading: true
|
loading: true,
|
||||||
};
|
}
|
||||||
timeout = 0;
|
timeout = 0
|
||||||
retrievedFromServer = false;
|
retrievedFromServer = false
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
const {
|
const {
|
||||||
history,
|
history,
|
||||||
match: {
|
match: {
|
||||||
params: { year, month, day }
|
params: { year, month, day },
|
||||||
}
|
},
|
||||||
} = this.props;
|
} = this.props
|
||||||
history.listen((location, action) => {
|
history.listen((location, action) => {
|
||||||
const [, year, month, day] = location.pathname.split("/");
|
const [, year, month, day] = location.pathname.split("/")
|
||||||
this.onRouteChanged(year, month, day);
|
this.onRouteChanged(year, month, day)
|
||||||
});
|
})
|
||||||
this.getDocRef(year, month, day, false);
|
this.getDocRef(year, month, day, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
onRouteChanged = (year, month, day) => {
|
onRouteChanged = (year, month, day) => {
|
||||||
this.setState({ loading: true });
|
this.setState({ loading: true })
|
||||||
this.getDocRef(year, month, day, false);
|
this.getDocRef(year, month, day, false)
|
||||||
};
|
}
|
||||||
|
|
||||||
getDocRef = (year, month, day, cacheFirst) => {
|
getDocRef = (year, month, day, cacheFirst) => {
|
||||||
const { firebase, authUser } = this.props;
|
const { firebase, authUser } = this.props
|
||||||
const getOptions = {
|
const getOptions = {
|
||||||
source: cacheFirst ? "cache" : "default"
|
source: cacheFirst ? "cache" : "default",
|
||||||
};
|
}
|
||||||
const docRef = firebase.db
|
const docRef = firebase.db
|
||||||
.collection("entries")
|
.collection("entries")
|
||||||
.doc(`${year}${month}${day}-${authUser.uid}`);
|
.doc(`${year}${month}${day}-${authUser.uid}`)
|
||||||
this.getData(docRef, getOptions);
|
this.getData(docRef, getOptions)
|
||||||
};
|
}
|
||||||
|
|
||||||
getData = (docRef, options) => {
|
getData = (docRef, options) => {
|
||||||
docRef
|
docRef
|
||||||
.get(options)
|
.get(options)
|
||||||
.then(doc => {
|
.then(doc => {
|
||||||
if (doc.data()) {
|
if (doc.data()) {
|
||||||
this.setState({ text: doc.data().text, loading: false });
|
this.setState({ text: doc.data().text, loading: false })
|
||||||
} else {
|
} else {
|
||||||
this.setState({ text: "", loading: false });
|
this.setState({ text: "", loading: false })
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(err => {
|
.catch(err => {
|
||||||
console.warn("entry not found in cache");
|
console.warn("entry not found in cache")
|
||||||
// for cache first, server second fetching, dangerous with potential overwriting of data
|
// for cache first, server second fetching, dangerous with potential overwriting of data
|
||||||
// docRef.get().then(doc => {
|
// docRef.get().then(doc => {
|
||||||
// if (doc.data()) {
|
// if (doc.data()) {
|
||||||
@@ -104,28 +104,28 @@ class Day extends Component {
|
|||||||
// this.setState({ text: "", loading: false });
|
// this.setState({ text: "", loading: false });
|
||||||
// }
|
// }
|
||||||
// });
|
// });
|
||||||
});
|
})
|
||||||
};
|
}
|
||||||
|
|
||||||
onChangeText = e => {
|
onChangeText = e => {
|
||||||
if (this.timeout) clearTimeout(this.timeout);
|
if (this.timeout) clearTimeout(this.timeout)
|
||||||
const text = e.target.value;
|
const text = e.target.value
|
||||||
|
|
||||||
this.setState({ text });
|
this.setState({ text })
|
||||||
this.timeout = setTimeout(() => {
|
this.timeout = setTimeout(() => {
|
||||||
console.log(text);
|
console.log(text)
|
||||||
this.saveText(text);
|
this.saveText(text)
|
||||||
}, AUTOSAVE_DELAY);
|
}, AUTOSAVE_DELAY)
|
||||||
};
|
}
|
||||||
|
|
||||||
saveText = text => {
|
saveText = text => {
|
||||||
const {
|
const {
|
||||||
match: {
|
match: {
|
||||||
params: { year, month, day }
|
params: { year, month, day },
|
||||||
},
|
},
|
||||||
firebase,
|
firebase,
|
||||||
authUser
|
authUser,
|
||||||
} = this.props;
|
} = this.props
|
||||||
firebase.db
|
firebase.db
|
||||||
.collection("entries")
|
.collection("entries")
|
||||||
.doc(`${year}${month}${day}-${authUser.uid}`)
|
.doc(`${year}${month}${day}-${authUser.uid}`)
|
||||||
@@ -134,24 +134,24 @@ class Day extends Component {
|
|||||||
text,
|
text,
|
||||||
day: Number(day),
|
day: Number(day),
|
||||||
year: Number(year),
|
year: Number(year),
|
||||||
month: Number(month)
|
month: Number(month),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
merge: true
|
merge: true,
|
||||||
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {
|
const {
|
||||||
match: {
|
match: {
|
||||||
params: { year, month, day }
|
params: { year, month, day },
|
||||||
},
|
},
|
||||||
theme
|
theme,
|
||||||
} = this.props;
|
} = this.props
|
||||||
const { text, loading } = this.state;
|
const { text, loading } = this.state
|
||||||
const currentDay = new Date(year, month - 1, day);
|
const currentDay = new Date(year, month - 1, day)
|
||||||
if (!currentDay) return;
|
if (!currentDay) return
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@@ -175,7 +175,7 @@ class Day extends Component {
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
);
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -184,4 +184,4 @@ export default compose(
|
|||||||
withTheme,
|
withTheme,
|
||||||
withAuthentication,
|
withAuthentication,
|
||||||
withRouter
|
withRouter
|
||||||
)(Day);
|
)(Day)
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
import Day from "./Day";
|
import Day from "./Day"
|
||||||
export default Day;
|
export default Day
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import React, { Component } from "react";
|
import React, { Component } from "react"
|
||||||
import { withRouter, Link } from "react-router-dom";
|
import { withRouter, Link } from "react-router-dom"
|
||||||
import { format } from "date-fns";
|
import { format } from "date-fns"
|
||||||
|
|
||||||
import { FirebaseContext } from "../../firebase";
|
import { FirebaseContext } from "../../firebase"
|
||||||
|
|
||||||
const LoginPage = ({ history }) => (
|
const LoginPage = ({ history }) => (
|
||||||
<div>
|
<div>
|
||||||
@@ -14,38 +14,38 @@ const LoginPage = ({ history }) => (
|
|||||||
Don't have an account? <Link to={"/register"}>Sign Up</Link>
|
Don't have an account? <Link to={"/register"}>Sign Up</Link>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
);
|
)
|
||||||
|
|
||||||
class LoginFormBase extends Component {
|
class LoginFormBase extends Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props)
|
||||||
|
|
||||||
this.state = { email: "", password: "", error: null };
|
this.state = { email: "", password: "", error: null }
|
||||||
}
|
}
|
||||||
|
|
||||||
onSubmit = event => {
|
onSubmit = event => {
|
||||||
event.preventDefault();
|
event.preventDefault()
|
||||||
const { email, password } = this.state;
|
const { email, password } = this.state
|
||||||
|
|
||||||
this.props.firebase
|
this.props.firebase
|
||||||
.doSignInWithEmailAndPassword(email, password)
|
.doSignInWithEmailAndPassword(email, password)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
this.setState({ email: "", password: "", error: null });
|
this.setState({ email: "", password: "", error: null })
|
||||||
this.props.history.push(format(new Date(), "/YYYY/MM/DD"));
|
this.props.history.push(format(new Date(), "/YYYY/MM/DD"))
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
this.setState({ error });
|
this.setState({ error })
|
||||||
});
|
})
|
||||||
};
|
}
|
||||||
|
|
||||||
onChange = event => {
|
onChange = event => {
|
||||||
this.setState({ [event.target.name]: event.target.value });
|
this.setState({ [event.target.name]: event.target.value })
|
||||||
};
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { email, password, error } = this.state;
|
const { email, password, error } = this.state
|
||||||
|
|
||||||
const isInvalid = password === "" || email === "";
|
const isInvalid = password === "" || email === ""
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<form onSubmit={this.onSubmit}>
|
<form onSubmit={this.onSubmit}>
|
||||||
@@ -69,12 +69,12 @@ class LoginFormBase extends Component {
|
|||||||
|
|
||||||
{error && <p>{error.message}</p>}
|
{error && <p>{error.message}</p>}
|
||||||
</form>
|
</form>
|
||||||
);
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const LoginForm = withRouter(LoginFormBase);
|
const LoginForm = withRouter(LoginFormBase)
|
||||||
|
|
||||||
export default LoginPage;
|
export default LoginPage
|
||||||
|
|
||||||
export { LoginForm };
|
export { LoginForm }
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
import Login from "./Login";
|
import Login from "./Login"
|
||||||
export default Login;
|
export default Login
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import React, { Component } from "react";
|
import React, { Component } from "react"
|
||||||
import { Link } from "react-router-dom";
|
import { Link } from "react-router-dom"
|
||||||
import styled from "@emotion/styled";
|
import styled from "@emotion/styled"
|
||||||
import {
|
import {
|
||||||
isAfter,
|
isAfter,
|
||||||
isThisYear,
|
isThisYear,
|
||||||
@@ -8,17 +8,17 @@ import {
|
|||||||
addMonths,
|
addMonths,
|
||||||
subMonths,
|
subMonths,
|
||||||
getDaysInMonth,
|
getDaysInMonth,
|
||||||
startOfMonth
|
startOfMonth,
|
||||||
} from "date-fns";
|
} from "date-fns"
|
||||||
|
|
||||||
import Seek from "../../Seek";
|
import Seek from "../../Seek"
|
||||||
|
|
||||||
const YearCardGrid = styled.div`
|
const YearCardGrid = styled.div`
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(auto-fit, minmax(80px, 1fr));
|
grid-template-columns: repeat(auto-fit, minmax(75px, 1fr));
|
||||||
grid-gap: 20px;
|
grid-gap: 20px;
|
||||||
margin-top: 20px;
|
margin-top: 20px;
|
||||||
`;
|
`
|
||||||
const YearCard = styled.div`
|
const YearCard = styled.div`
|
||||||
color: ${props =>
|
color: ${props =>
|
||||||
props.disabled
|
props.disabled
|
||||||
@@ -26,39 +26,39 @@ const YearCard = styled.div`
|
|||||||
: props.theme.colors.secondary};
|
: props.theme.colors.secondary};
|
||||||
border: 1px solid;
|
border: 1px solid;
|
||||||
border-color: ${props => props.theme.colors.quarternary};
|
border-color: ${props => props.theme.colors.quarternary};
|
||||||
padding: 30px;
|
padding: 25px;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
&:hover {
|
&:hover {
|
||||||
border-color: ${props => !props.disabled && props.theme.colors.tertiary};
|
border-color: ${props => !props.disabled && props.theme.colors.tertiary};
|
||||||
}
|
}
|
||||||
`;
|
`
|
||||||
|
|
||||||
class Month extends Component {
|
class Month extends Component {
|
||||||
render() {
|
render() {
|
||||||
const {
|
const {
|
||||||
match: {
|
match: {
|
||||||
params: { year, month }
|
params: { year, month },
|
||||||
}
|
},
|
||||||
} = this.props;
|
} = this.props
|
||||||
const currentDay = new Date(year, month - 1);
|
const currentDay = new Date(year, month - 1)
|
||||||
|
|
||||||
// include all months unless it's this year
|
// include all months unless it's this year
|
||||||
let dayIndexesToInclude = 31;
|
let dayIndexesToInclude = 31
|
||||||
if (isThisYear(currentDay)) {
|
if (isThisYear(currentDay)) {
|
||||||
dayIndexesToInclude = new Date().getDate();
|
dayIndexesToInclude = new Date().getDate()
|
||||||
}
|
}
|
||||||
|
|
||||||
let yearCards = [];
|
let yearCards = []
|
||||||
for (let i = 0; i < getDaysInMonth(currentDay); i++) {
|
for (let i = 0; i < getDaysInMonth(currentDay); i++) {
|
||||||
const isDisabled = dayIndexesToInclude <= i;
|
const isDisabled = dayIndexesToInclude <= i
|
||||||
if (isDisabled) {
|
if (isDisabled) {
|
||||||
yearCards.push(
|
yearCards.push(
|
||||||
<YearCard disabled={isDisabled} key={i}>
|
<YearCard disabled={isDisabled} key={i}>
|
||||||
{i + 1}
|
{i + 1}
|
||||||
</YearCard>
|
</YearCard>
|
||||||
);
|
)
|
||||||
} else {
|
} else {
|
||||||
yearCards.push(
|
yearCards.push(
|
||||||
<Link
|
<Link
|
||||||
@@ -68,7 +68,7 @@ class Month extends Component {
|
|||||||
>
|
>
|
||||||
<YearCard key={i}>{i + 1}</YearCard>
|
<YearCard key={i}>{i + 1}</YearCard>
|
||||||
</Link>
|
</Link>
|
||||||
);
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -85,8 +85,8 @@ class Month extends Component {
|
|||||||
/>
|
/>
|
||||||
<YearCardGrid>{yearCards}</YearCardGrid>
|
<YearCardGrid>{yearCards}</YearCardGrid>
|
||||||
</>
|
</>
|
||||||
);
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Month;
|
export default Month
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
import Month from "./Month";
|
import Month from "./Month"
|
||||||
export default Month;
|
export default Month
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import React, { Component } from "react";
|
import React, { Component } from "react"
|
||||||
import { withRouter } from "react-router-dom";
|
import { withRouter } from "react-router-dom"
|
||||||
|
|
||||||
import { FirebaseContext } from "../../firebase";
|
import { FirebaseContext } from "../../firebase"
|
||||||
|
|
||||||
const RegisterPage = ({ history }) => (
|
const RegisterPage = ({ history }) => (
|
||||||
<div>
|
<div>
|
||||||
@@ -10,24 +10,24 @@ const RegisterPage = ({ history }) => (
|
|||||||
{firebase => <RegisterForm history={history} firebase={firebase} />}
|
{firebase => <RegisterForm history={history} firebase={firebase} />}
|
||||||
</FirebaseContext.Consumer>
|
</FirebaseContext.Consumer>
|
||||||
</div>
|
</div>
|
||||||
);
|
)
|
||||||
|
|
||||||
class RegisterForm extends Component {
|
class RegisterForm extends Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props)
|
||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
username: "",
|
username: "",
|
||||||
email: "",
|
email: "",
|
||||||
passwordOne: "",
|
passwordOne: "",
|
||||||
passwordTwo: "",
|
passwordTwo: "",
|
||||||
error: null
|
error: null,
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onSubmit = event => {
|
onSubmit = event => {
|
||||||
const { email, passwordOne } = this.state;
|
const { email, passwordOne } = this.state
|
||||||
const { firebase } = this.props;
|
const { firebase } = this.props
|
||||||
|
|
||||||
firebase
|
firebase
|
||||||
.doCreateUserWithEmailAndPassword(email, passwordOne)
|
.doCreateUserWithEmailAndPassword(email, passwordOne)
|
||||||
@@ -37,37 +37,37 @@ class RegisterForm extends Component {
|
|||||||
email: "",
|
email: "",
|
||||||
passwordOne: "",
|
passwordOne: "",
|
||||||
passwordTwo: "",
|
passwordTwo: "",
|
||||||
error: null
|
error: null,
|
||||||
});
|
})
|
||||||
const { user } = result;
|
const { user } = result
|
||||||
console.log(user);
|
console.log(user)
|
||||||
firebase.db
|
firebase.db
|
||||||
.collection("users")
|
.collection("users")
|
||||||
.doc(user.uid)
|
.doc(user.uid)
|
||||||
.set({
|
.set({
|
||||||
email: user.email,
|
email: user.email,
|
||||||
theme: "LIGHT"
|
theme: "LIGHT",
|
||||||
});
|
})
|
||||||
this.props.history.push("/home");
|
this.props.history.push("/home")
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
this.setState({ error });
|
this.setState({ error })
|
||||||
});
|
})
|
||||||
|
|
||||||
event.preventDefault();
|
event.preventDefault()
|
||||||
};
|
}
|
||||||
|
|
||||||
onChange = event => {
|
onChange = event => {
|
||||||
this.setState({ [event.target.name]: event.target.value });
|
this.setState({ [event.target.name]: event.target.value })
|
||||||
};
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { username, email, passwordOne, passwordTwo, error } = this.state;
|
const { username, email, passwordOne, passwordTwo, error } = this.state
|
||||||
const isInvalid =
|
const isInvalid =
|
||||||
passwordOne !== passwordTwo ||
|
passwordOne !== passwordTwo ||
|
||||||
passwordOne === "" ||
|
passwordOne === "" ||
|
||||||
email === "" ||
|
email === "" ||
|
||||||
username === "";
|
username === ""
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<form onSubmit={this.onSubmit}>
|
<form onSubmit={this.onSubmit}>
|
||||||
@@ -105,10 +105,10 @@ class RegisterForm extends Component {
|
|||||||
|
|
||||||
{error && <p>{error.message}</p>}
|
{error && <p>{error.message}</p>}
|
||||||
</form>
|
</form>
|
||||||
);
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default withRouter(RegisterPage);
|
export default withRouter(RegisterPage)
|
||||||
|
|
||||||
export { RegisterForm };
|
export { RegisterForm }
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
import Register from "./Register";
|
import Register from "./Register"
|
||||||
export default Register;
|
export default Register
|
||||||
|
|||||||
@@ -1,31 +1,31 @@
|
|||||||
import React from "react";
|
import React from "react"
|
||||||
import { withFirebase } from "../../firebase";
|
import { withFirebase } from "../../firebase"
|
||||||
|
|
||||||
import SignOut from "../../SignOut";
|
import SignOut from "../../SignOut"
|
||||||
|
|
||||||
class User extends React.Component {
|
class User extends React.Component {
|
||||||
state = {
|
state = {
|
||||||
name: ""
|
name: "",
|
||||||
};
|
}
|
||||||
|
|
||||||
updateInput = e => {
|
updateInput = e => {
|
||||||
this.setState({
|
this.setState({
|
||||||
[e.target.name]: e.target.value
|
[e.target.name]: e.target.value,
|
||||||
});
|
})
|
||||||
};
|
}
|
||||||
|
|
||||||
addUser = e => {
|
addUser = e => {
|
||||||
e.preventDefault();
|
e.preventDefault()
|
||||||
const { firebase } = this.props;
|
const { firebase } = this.props
|
||||||
|
|
||||||
firebase.db
|
firebase.db
|
||||||
.collection("users")
|
.collection("users")
|
||||||
.doc()
|
.doc()
|
||||||
.add({
|
.add({
|
||||||
name: this.state.name
|
name: this.state.name,
|
||||||
});
|
})
|
||||||
this.setState({ name: "" });
|
this.setState({ name: "" })
|
||||||
};
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
@@ -42,8 +42,8 @@ class User extends React.Component {
|
|||||||
<button type="submit">Submit</button>
|
<button type="submit">Submit</button>
|
||||||
</form>
|
</form>
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
);
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default withFirebase(User);
|
export default withFirebase(User)
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
import User from "./User";
|
import User from "./User"
|
||||||
export default User;
|
export default User
|
||||||
|
|||||||
@@ -1,18 +1,18 @@
|
|||||||
import React, { Component } from "react";
|
import React, { Component } from "react"
|
||||||
import { Link } from "react-router-dom";
|
import { Link } from "react-router-dom"
|
||||||
import styled from "@emotion/styled";
|
import styled from "@emotion/styled"
|
||||||
import { addYears, subYears, format, isThisYear, getMonth } from "date-fns";
|
import { addYears, subYears, format, isThisYear, getMonth } from "date-fns"
|
||||||
import { withTheme } from "emotion-theming";
|
import { withTheme } from "emotion-theming"
|
||||||
|
|
||||||
import { months } from "../../../utils/date";
|
import { months } from "../../../utils/date"
|
||||||
import Seek from "../../Seek";
|
import Seek from "../../Seek"
|
||||||
|
|
||||||
const MonthCardGrid = styled.div`
|
const MonthCardGrid = styled.div`
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
|
grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
|
||||||
grid-gap: 20px;
|
grid-gap: 20px;
|
||||||
margin-top: 20px;
|
margin-top: 20px;
|
||||||
`;
|
`
|
||||||
const MonthCard = styled.div`
|
const MonthCard = styled.div`
|
||||||
color: ${props =>
|
color: ${props =>
|
||||||
props.disabled
|
props.disabled
|
||||||
@@ -27,21 +27,21 @@ const MonthCard = styled.div`
|
|||||||
&:hover {
|
&:hover {
|
||||||
border-color: ${props => !props.disabled && props.theme.colors.tertiary};
|
border-color: ${props => !props.disabled && props.theme.colors.tertiary};
|
||||||
}
|
}
|
||||||
`;
|
`
|
||||||
|
|
||||||
class Year extends Component {
|
class Year extends Component {
|
||||||
render() {
|
render() {
|
||||||
const {
|
const {
|
||||||
match: {
|
match: {
|
||||||
params: { year }
|
params: { year },
|
||||||
}
|
},
|
||||||
} = this.props;
|
} = this.props
|
||||||
const currentDate = new Date(year, 0, 1);
|
const currentDate = new Date(year, 0, 1)
|
||||||
|
|
||||||
// include all months unless it's this year
|
// include all months unless it's this year
|
||||||
let monthIndexesToInclude = 11;
|
let monthIndexesToInclude = 11
|
||||||
if (isThisYear(currentDate)) {
|
if (isThisYear(currentDate)) {
|
||||||
monthIndexesToInclude = getMonth(new Date());
|
monthIndexesToInclude = getMonth(new Date())
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
@@ -53,7 +53,7 @@ class Year extends Component {
|
|||||||
/>
|
/>
|
||||||
<MonthCardGrid>
|
<MonthCardGrid>
|
||||||
{months.long.map((month, index) => {
|
{months.long.map((month, index) => {
|
||||||
const isDisabled = monthIndexesToInclude < index;
|
const isDisabled = monthIndexesToInclude < index
|
||||||
return isDisabled ? (
|
return isDisabled ? (
|
||||||
<MonthCard key={index} disabled={isDisabled}>
|
<MonthCard key={index} disabled={isDisabled}>
|
||||||
{month}
|
{month}
|
||||||
@@ -66,12 +66,12 @@ class Year extends Component {
|
|||||||
>
|
>
|
||||||
<MonthCard>{month}</MonthCard>
|
<MonthCard>{month}</MonthCard>
|
||||||
</Link>
|
</Link>
|
||||||
);
|
)
|
||||||
})}
|
})}
|
||||||
</MonthCardGrid>
|
</MonthCardGrid>
|
||||||
</div>
|
</div>
|
||||||
);
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default withTheme(Year);
|
export default withTheme(Year)
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
import Year from "./Year";
|
import Year from "./Year"
|
||||||
export default Year;
|
export default Year
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import React from "react";
|
import React from "react"
|
||||||
|
|
||||||
const AuthUserContext = React.createContext(null);
|
const AuthUserContext = React.createContext(null)
|
||||||
|
|
||||||
export default AuthUserContext;
|
export default AuthUserContext
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import AuthUserContext from "./context";
|
import AuthUserContext from "./context"
|
||||||
import withAuthentication from "./withAuthentication";
|
import withAuthentication from "./withAuthentication"
|
||||||
|
|
||||||
export { AuthUserContext, withAuthentication };
|
export { AuthUserContext, withAuthentication }
|
||||||
|
|||||||
@@ -1,39 +1,39 @@
|
|||||||
import React from "react";
|
import React from "react"
|
||||||
|
|
||||||
import AuthUserContext from "./context";
|
import AuthUserContext from "./context"
|
||||||
import { withFirebase } from "../firebase";
|
import { withFirebase } from "../firebase"
|
||||||
|
|
||||||
const withAuthentication = Component => {
|
const withAuthentication = Component => {
|
||||||
class WithAuthentication extends React.Component {
|
class WithAuthentication extends React.Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props)
|
||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
authUser: JSON.parse(localStorage.getItem("authUser"))
|
authUser: JSON.parse(localStorage.getItem("authUser")),
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
this.listener = this.props.firebase.auth.onAuthStateChanged(
|
this.listener = this.props.firebase.auth.onAuthStateChanged(
|
||||||
authUser => {
|
authUser => {
|
||||||
localStorage.setItem("authUser", JSON.stringify(authUser));
|
localStorage.setItem("authUser", JSON.stringify(authUser))
|
||||||
this.setState({
|
this.setState({
|
||||||
authUser: {
|
authUser: {
|
||||||
uid: authUser.uid,
|
uid: authUser.uid,
|
||||||
email: authUser.email,
|
email: authUser.email,
|
||||||
emailVerified: authUser.emailVerified,
|
emailVerified: authUser.emailVerified,
|
||||||
}
|
},
|
||||||
});
|
})
|
||||||
},
|
},
|
||||||
() => {
|
() => {
|
||||||
localStorage.removeItem("authUser");
|
localStorage.removeItem("authUser")
|
||||||
this.setState({ authUser: null });
|
this.setState({ authUser: null })
|
||||||
}
|
}
|
||||||
);
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
this.listener();
|
this.listener()
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
@@ -41,11 +41,11 @@ const withAuthentication = Component => {
|
|||||||
<AuthUserContext.Provider value={this.state.authUser}>
|
<AuthUserContext.Provider value={this.state.authUser}>
|
||||||
<Component authUser={this.state.authUser} {...this.props} />
|
<Component authUser={this.state.authUser} {...this.props} />
|
||||||
</AuthUserContext.Provider>
|
</AuthUserContext.Provider>
|
||||||
);
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return withFirebase(WithAuthentication);
|
return withFirebase(WithAuthentication)
|
||||||
};
|
}
|
||||||
|
|
||||||
export default withAuthentication;
|
export default withAuthentication
|
||||||
|
|||||||
16
src/index.js
16
src/index.js
@@ -1,19 +1,19 @@
|
|||||||
import React from "react";
|
import React from "react"
|
||||||
import ReactDOM from "react-dom";
|
import ReactDOM from "react-dom"
|
||||||
|
|
||||||
import "./index.css";
|
import "./index.css"
|
||||||
import App from "./App";
|
import App from "./App"
|
||||||
import * as serviceWorker from "./serviceWorker";
|
import * as serviceWorker from "./serviceWorker"
|
||||||
import Firebase, { FirebaseContext } from "./components/firebase";
|
import Firebase, { FirebaseContext } from "./components/firebase"
|
||||||
|
|
||||||
ReactDOM.render(
|
ReactDOM.render(
|
||||||
<FirebaseContext.Provider value={new Firebase()}>
|
<FirebaseContext.Provider value={new Firebase()}>
|
||||||
<App />
|
<App />
|
||||||
</FirebaseContext.Provider>,
|
</FirebaseContext.Provider>,
|
||||||
document.getElementById("root")
|
document.getElementById("root")
|
||||||
);
|
)
|
||||||
|
|
||||||
// If you want your app to work offline and load faster, you can change
|
// If you want your app to work offline and load faster, you can change
|
||||||
// unregister() to register() below. Note this comes with some pitfalls.
|
// unregister() to register() below. Note this comes with some pitfalls.
|
||||||
// Learn more about service workers: https://bit.ly/CRA-PWA
|
// Learn more about service workers: https://bit.ly/CRA-PWA
|
||||||
serviceWorker.register();
|
serviceWorker.register()
|
||||||
|
|||||||
@@ -18,25 +18,25 @@ const isLocalhost = Boolean(
|
|||||||
window.location.hostname.match(
|
window.location.hostname.match(
|
||||||
/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
|
/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
|
||||||
)
|
)
|
||||||
);
|
)
|
||||||
|
|
||||||
export function register(config) {
|
export function register(config) {
|
||||||
if (process.env.NODE_ENV === "production" && "serviceWorker" in navigator) {
|
if (process.env.NODE_ENV === "production" && "serviceWorker" in navigator) {
|
||||||
// The URL constructor is available in all browsers that support SW.
|
// The URL constructor is available in all browsers that support SW.
|
||||||
const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href);
|
const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href)
|
||||||
if (publicUrl.origin !== window.location.origin) {
|
if (publicUrl.origin !== window.location.origin) {
|
||||||
// Our service worker won't work if PUBLIC_URL is on a different origin
|
// Our service worker won't work if PUBLIC_URL is on a different origin
|
||||||
// from what our page is served on. This might happen if a CDN is used to
|
// from what our page is served on. This might happen if a CDN is used to
|
||||||
// serve assets; see https://github.com/facebook/create-react-app/issues/2374
|
// serve assets; see https://github.com/facebook/create-react-app/issues/2374
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
window.addEventListener("load", () => {
|
window.addEventListener("load", () => {
|
||||||
const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;
|
const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`
|
||||||
|
|
||||||
if (isLocalhost) {
|
if (isLocalhost) {
|
||||||
// This is running on localhost. Let's check if a service worker still exists or not.
|
// This is running on localhost. Let's check if a service worker still exists or not.
|
||||||
checkValidServiceWorker(swUrl, config);
|
checkValidServiceWorker(swUrl, config)
|
||||||
|
|
||||||
// Add some additional logging to localhost, pointing developers to the
|
// Add some additional logging to localhost, pointing developers to the
|
||||||
// service worker/PWA documentation.
|
// service worker/PWA documentation.
|
||||||
@@ -44,13 +44,13 @@ export function register(config) {
|
|||||||
console.log(
|
console.log(
|
||||||
"This web app is being served cache-first by a service " +
|
"This web app is being served cache-first by a service " +
|
||||||
"worker. To learn more, visit https://bit.ly/CRA-PWA"
|
"worker. To learn more, visit https://bit.ly/CRA-PWA"
|
||||||
);
|
)
|
||||||
});
|
})
|
||||||
} else {
|
} else {
|
||||||
// Is not localhost. Just register service worker
|
// Is not localhost. Just register service worker
|
||||||
registerValidSW(swUrl, config);
|
registerValidSW(swUrl, config)
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -59,9 +59,9 @@ function registerValidSW(swUrl, config) {
|
|||||||
.register(swUrl)
|
.register(swUrl)
|
||||||
.then(registration => {
|
.then(registration => {
|
||||||
registration.onupdatefound = () => {
|
registration.onupdatefound = () => {
|
||||||
const installingWorker = registration.installing;
|
const installingWorker = registration.installing
|
||||||
if (installingWorker == null) {
|
if (installingWorker == null) {
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
installingWorker.onstatechange = () => {
|
installingWorker.onstatechange = () => {
|
||||||
if (installingWorker.state === "installed") {
|
if (installingWorker.state === "installed") {
|
||||||
@@ -72,30 +72,30 @@ function registerValidSW(swUrl, config) {
|
|||||||
console.log(
|
console.log(
|
||||||
"New content is available and will be used when all " +
|
"New content is available and will be used when all " +
|
||||||
"tabs for this page are closed. See https://bit.ly/CRA-PWA."
|
"tabs for this page are closed. See https://bit.ly/CRA-PWA."
|
||||||
);
|
)
|
||||||
|
|
||||||
// Execute callback
|
// Execute callback
|
||||||
if (config && config.onUpdate) {
|
if (config && config.onUpdate) {
|
||||||
config.onUpdate(registration);
|
config.onUpdate(registration)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// At this point, everything has been precached.
|
// At this point, everything has been precached.
|
||||||
// It's the perfect time to display a
|
// It's the perfect time to display a
|
||||||
// "Content is cached for offline use." message.
|
// "Content is cached for offline use." message.
|
||||||
console.log("Content is cached for offline use.");
|
console.log("Content is cached for offline use.")
|
||||||
|
|
||||||
// Execute callback
|
// Execute callback
|
||||||
if (config && config.onSuccess) {
|
if (config && config.onSuccess) {
|
||||||
config.onSuccess(registration);
|
config.onSuccess(registration)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
|
||||||
};
|
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
console.error("Error during service worker registration:", error);
|
console.error("Error during service worker registration:", error)
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkValidServiceWorker(swUrl, config) {
|
function checkValidServiceWorker(swUrl, config) {
|
||||||
@@ -103,7 +103,7 @@ function checkValidServiceWorker(swUrl, config) {
|
|||||||
fetch(swUrl)
|
fetch(swUrl)
|
||||||
.then(response => {
|
.then(response => {
|
||||||
// Ensure service worker exists, and that we really are getting a JS file.
|
// Ensure service worker exists, and that we really are getting a JS file.
|
||||||
const contentType = response.headers.get("content-type");
|
const contentType = response.headers.get("content-type")
|
||||||
if (
|
if (
|
||||||
response.status === 404 ||
|
response.status === 404 ||
|
||||||
(contentType != null && contentType.indexOf("javascript") === -1)
|
(contentType != null && contentType.indexOf("javascript") === -1)
|
||||||
@@ -111,25 +111,25 @@ function checkValidServiceWorker(swUrl, config) {
|
|||||||
// No service worker found. Probably a different app. Reload the page.
|
// No service worker found. Probably a different app. Reload the page.
|
||||||
navigator.serviceWorker.ready.then(registration => {
|
navigator.serviceWorker.ready.then(registration => {
|
||||||
registration.unregister().then(() => {
|
registration.unregister().then(() => {
|
||||||
window.location.reload();
|
window.location.reload()
|
||||||
});
|
})
|
||||||
});
|
})
|
||||||
} else {
|
} else {
|
||||||
// Service worker found. Proceed as normal.
|
// Service worker found. Proceed as normal.
|
||||||
registerValidSW(swUrl, config);
|
registerValidSW(swUrl, config)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
console.log(
|
console.log(
|
||||||
"No internet connection found. App is running in offline mode."
|
"No internet connection found. App is running in offline mode."
|
||||||
);
|
)
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export function unregister() {
|
export function unregister() {
|
||||||
if ("serviceWorker" in navigator) {
|
if ("serviceWorker" in navigator) {
|
||||||
navigator.serviceWorker.ready.then(registration => {
|
navigator.serviceWorker.ready.then(registration => {
|
||||||
registration.unregister();
|
registration.unregister()
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,5 +3,6 @@ export const SIZES = {
|
|||||||
small: "1rem",
|
small: "1rem",
|
||||||
normal: "1.25rem",
|
normal: "1.25rem",
|
||||||
medium: "1.5rem",
|
medium: "1.5rem",
|
||||||
large: "2rem"
|
large: "2rem",
|
||||||
};
|
maxWidth: "600px",
|
||||||
|
}
|
||||||
|
|||||||
@@ -9,8 +9,8 @@ const theme = {
|
|||||||
quarternary: "#EAEAEA",
|
quarternary: "#EAEAEA",
|
||||||
headerBackground: "#FAFBFC",
|
headerBackground: "#FAFBFC",
|
||||||
bodyBackground: "#FFF",
|
bodyBackground: "#FFF",
|
||||||
hover: "hsla(233, 5%, 31%, 0.12)"
|
hover: "hsla(233, 5%, 31%, 0.12)",
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
DARK: {
|
DARK: {
|
||||||
name: "Dark",
|
name: "Dark",
|
||||||
@@ -22,9 +22,9 @@ const theme = {
|
|||||||
quarternary: "#3E4B62",
|
quarternary: "#3E4B62",
|
||||||
headerBackground: "#272f3d",
|
headerBackground: "#272f3d",
|
||||||
bodyBackground: "#262B34",
|
bodyBackground: "#262B34",
|
||||||
hover: "hsla(233, 100%, 96%, 0.12)"
|
hover: "hsla(233, 100%, 96%, 0.12)",
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
};
|
}
|
||||||
|
|
||||||
export default theme;
|
export default theme
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
export const pad = n => (n < 10 ? "0" : "") + n;
|
export const pad = n => (n < 10 ? "0" : "") + n
|
||||||
|
|
||||||
export const todayUrl = (date = new Date()) =>
|
export const todayUrl = (date = new Date()) =>
|
||||||
`/${date.getFullYear()}/${pad(date.getMonth() + 1)}/${pad(date.getDate())}/`;
|
`/${date.getFullYear()}/${pad(date.getMonth() + 1)}/${pad(date.getDate())}/`
|
||||||
|
|
||||||
export const yearUrl = (date = new Date()) => `/${date.getFullYear()}/`;
|
export const yearUrl = (date = new Date()) => `/${date.getFullYear()}/`
|
||||||
|
|
||||||
export const months = {
|
export const months = {
|
||||||
long: Array.from({ length: 12 }, (x, index) =>
|
long: Array.from({ length: 12 }, (x, index) =>
|
||||||
new Date(0, index).toLocaleDateString("en-US", { month: "long" })
|
new Date(0, index).toLocaleDateString("en-US", { month: "long" })
|
||||||
)
|
),
|
||||||
};
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user