aboutsummaryrefslogtreecommitdiffstats
path: root/pages
diff options
context:
space:
mode:
authorGravatar piotrruss <mail@pruss.it> 2021-08-09 21:36:03 +0200
committerGravatar piotrruss <mail@pruss.it> 2021-08-09 21:37:03 +0200
commit464e470441287572cfda8d95484f781236b9db35 (patch)
tree87177837cb6ee6ee000f0d39fa5ba7ee6bb2943e /pages
downloadmy_apps-464e470441287572cfda8d95484f781236b9db35.tar.gz
my_apps-464e470441287572cfda8d95484f781236b9db35.tar.bz2
my_apps-464e470441287572cfda8d95484f781236b9db35.zip
init commit
Diffstat (limited to 'pages')
-rw-r--r--pages/_app.js20
-rw-r--r--pages/api/login.js29
-rw-r--r--pages/api/logout.js6
-rw-r--r--pages/api/note/[id].js30
-rw-r--r--pages/api/notes.js101
-rw-r--r--pages/api/register.js35
-rw-r--r--pages/api/user.js22
-rw-r--r--pages/api/verify.js45
-rw-r--r--pages/index.js67
-rw-r--r--pages/login.js26
-rw-r--r--pages/register.js24
-rw-r--r--pages/verify.js109
12 files changed, 514 insertions, 0 deletions
diff --git a/pages/_app.js b/pages/_app.js
new file mode 100644
index 0000000..5196b22
--- /dev/null
+++ b/pages/_app.js
@@ -0,0 +1,20 @@
+import { SWRConfig } from 'swr'
+import fetchJson from 'lib/fetchJson'
+import '/styles/styles.scss'
+
+function MyApp({Component, pageProps}) {
+ return (
+ <SWRConfig
+ value={{
+ fetcher: fetchJson,
+ onError: (err) => {
+ console.error(err)
+ },
+ }}
+ >
+ <Component {...pageProps} />
+ </SWRConfig>
+ )
+}
+
+export default MyApp
diff --git a/pages/api/login.js b/pages/api/login.js
new file mode 100644
index 0000000..30edda1
--- /dev/null
+++ b/pages/api/login.js
@@ -0,0 +1,29 @@
+import withSession from 'lib/withSession'
+import dbConnect from 'lib/dbConnect'
+import User from 'models/User'
+
+export default withSession(async (req, res) => {
+ const {method} = req
+
+ await dbConnect()
+
+ switch (method) {
+ case 'POST':
+ try {
+ const {_id, email, isVerified, noteList} = await User.findByCredentials(req.body.email, req.body.password);
+ if (!email) { throw new Error('Something went wrong') }
+
+ const user = {_id, email, isVerified, isLoggedIn: true, noteList}
+ req.session.set('user', user)
+ await req.session.save()
+ res.status(201).json(user)
+ } catch (error) {
+ res.status(400).json({isLoggedIn: false})
+ }
+ break
+ default:
+ res.status(400).send({isLoggedIn: false})
+ break
+ }
+})
+
diff --git a/pages/api/logout.js b/pages/api/logout.js
new file mode 100644
index 0000000..8c7a766
--- /dev/null
+++ b/pages/api/logout.js
@@ -0,0 +1,6 @@
+import withSession from 'lib/withSession'
+
+export default withSession(async (req, res) => {
+ req.session.destroy()
+ res.json({isLoggedIn: false})
+})
diff --git a/pages/api/note/[id].js b/pages/api/note/[id].js
new file mode 100644
index 0000000..8ba3b70
--- /dev/null
+++ b/pages/api/note/[id].js
@@ -0,0 +1,30 @@
+import dbConnect from 'lib/dbConnect'
+import withSession from 'lib/withSession'
+import Note from 'models/Note'
+
+export default withSession(async (req, res) => {
+ const { id } = req.query
+ await dbConnect()
+
+ switch (req.method) {
+ case 'GET':
+ try {
+ const user = req.session.get('user')
+
+ if (!user || !user?.isVerified || !id ) {
+ throw new Error('Something went wrong')
+ }
+
+ const note = await Note.findById(id)
+
+ if (!note) {
+ throw new Error('Something went wrong')
+ }
+
+ res.status(200).json(note)
+ } catch (error) {
+ res.status(400).json({error: true})
+ }
+ break
+ }
+})
diff --git a/pages/api/notes.js b/pages/api/notes.js
new file mode 100644
index 0000000..73a7217
--- /dev/null
+++ b/pages/api/notes.js
@@ -0,0 +1,101 @@
+import dbConnect from 'lib/dbConnect'
+import withSession from 'lib/withSession'
+import NoteList from 'models/NoteList'
+import Note from 'models/Note'
+
+export default withSession(async (req, res) => {
+ await dbConnect()
+
+ switch (req.method) {
+ case 'GET':
+ try {
+ const user = req.session.get('user')
+
+ if (!user || !user.isVerified) {
+ throw new Error('Something went wrong')
+ }
+
+ const {notes} = await NoteList.findById(user.noteList)
+
+ res.status(200).json(notes)
+ } catch (error) {
+ res.status(400).json([])
+ }
+ break
+ case 'POST':
+ try {
+ const user = req.session.get('user')
+ const {title, content} = req.body
+
+ if (!user || !user?.isVerified || !content) {
+ throw new Error('Something went wrong')
+ }
+
+ const note = await Note.create({content})
+
+ const noteList = await NoteList.findById(user.noteList)
+ noteList.notes.push({title: title ? title : 'No title', noteId: note})
+ await noteList.save()
+
+ res.status(200).json(noteList.notes)
+ } catch (error) {
+ res.status(400).json([])
+ }
+ break
+ case 'DELETE':
+ try {
+ const user = req.session.get('user')
+ const {_id} = req.body
+
+ if (!user || !user?.isVerified || !_id) {
+ throw new Error('Something went wrong')
+ }
+
+ const noteList = await NoteList.findById(user.noteList)
+ const noteId = noteList.notes
+ .find(n => n._id.toString() === _id.toString()).noteId
+
+ if (!noteList || !noteId) {
+ throw new Error('Something went wrong')
+ }
+
+ await Note.findByIdAndDelete(noteId)
+
+ noteList.notes.pull(_id)
+ await noteList.save()
+
+ res.status(200).json(noteList.notes)
+ } catch (error) {
+ res.status(400).json([])
+ }
+ break
+ case 'PUT':
+ try {
+ const user = req.session.get('user')
+ const {_id, title, noteId, content} = req.body
+
+ if (!user || !user?.isVerified || !_id || !content) {
+ throw new Error('Something went wrong')
+ }
+
+ await Note.findByIdAndUpdate(noteId, {content}, {new: true})
+
+ const notes = await NoteList.findOneAndUpdate(
+ { _id: user.noteList, "notes.noteId": noteId },
+ { $set: { "notes.$.title": title ? title : 'No title' } },
+ { new: true }
+ )
+
+ res.status(200).json(notes)
+ } catch (error) {
+ console.log(error)
+ res.status(400).json([])
+ }
+ break
+ default:
+ res.status(400).send()
+ break
+ }
+})
+
+
diff --git a/pages/api/register.js b/pages/api/register.js
new file mode 100644
index 0000000..f89e347
--- /dev/null
+++ b/pages/api/register.js
@@ -0,0 +1,35 @@
+import dbConnect from 'lib/dbConnect'
+import withSession from 'lib/withSession'
+import sendMail from 'lib/sendMail'
+import {subject, text, html} from 'helpers/email'
+import User from 'models/User'
+import NoteList from 'models/NoteList'
+
+export default withSession(async (req, res) => {
+ await dbConnect()
+
+ switch (req.method) {
+ case 'POST':
+ try {
+ const noteList = await NoteList.create({})
+
+ const {_id, email, verificationKey: key} = await User.create({...req.body, noteList})
+ if (!email) { throw new Error('Something went wrong') }
+
+ sendMail(req.body.email, subject, text(key), html(key))
+
+ const user = {_id, email, noteList, isVerified: false, isLoggedIn: true}
+ req.session.set('user', user)
+ await req.session.save()
+ res.status(201).json(user)
+ } catch (error) {
+ console.log(error)
+ res.status(400).json({isLoggedIn: false})
+ }
+ break
+ default:
+ res.status(400).json({isLoggedIn: false})
+ break
+ }
+})
+
diff --git a/pages/api/user.js b/pages/api/user.js
new file mode 100644
index 0000000..0b308f7
--- /dev/null
+++ b/pages/api/user.js
@@ -0,0 +1,22 @@
+import dbConnect from 'lib/dbConnect'
+import withSession from 'lib/withSession'
+import User from 'models/User'
+
+export default withSession(async (req, res) => {
+ await dbConnect()
+
+ const user = req.session.get('user')
+ const state = await User.state(user._id)
+
+ if (user) {
+ res.json({
+ isLoggedIn: true,
+ ...user,
+ ...state
+ })
+ } else {
+ res.json({
+ isLoggedIn: false,
+ })
+ }
+})
diff --git a/pages/api/verify.js b/pages/api/verify.js
new file mode 100644
index 0000000..1606dbc
--- /dev/null
+++ b/pages/api/verify.js
@@ -0,0 +1,45 @@
+import withSession from 'lib/withSession'
+import dbConnect from 'lib/dbConnect'
+import sendMail from 'lib/sendMail'
+import User from 'models/User'
+import {subject, text, html} from 'helpers/email'
+
+export default withSession(async (req, res) => {
+ await dbConnect()
+
+ switch (req.method) {
+ case 'GET':
+ try {
+ const {email} = req.session.get('user')
+ if (!email) { throw new Error('Something went wrong') }
+
+ const key = await User.getVerificationKey(email)
+ if (!key) { throw new Error('Something went wrong') }
+
+ const response = await sendMail(email, subject, text(key), html(key))
+ if (!response?.accepted?.length) { throw new Error('Something went wrong') }
+
+ res.status(204).send()
+ } catch (error) {
+ res.status(400).send()
+ }
+ break
+ case 'POST':
+ try {
+ if (req.body.key) {
+ const user = await User.verifyUser(req.body._id, req.body.key)
+ req.session.set('user', user)
+ await req.session.save()
+ res.status(200).json(user)
+ }
+ } catch (error) {
+ console.log(error)
+ res.status(400).send()
+ }
+ break
+ default:
+ res.status(400).send()
+ break
+ }
+})
+
diff --git a/pages/index.js b/pages/index.js
new file mode 100644
index 0000000..9df0acf
--- /dev/null
+++ b/pages/index.js
@@ -0,0 +1,67 @@
+import React, { useState ,useRef } from 'react'
+import useUser from 'lib/useUser'
+import {Layout, App} from 'components'
+import {open} from 'helpers/windowActions'
+import {Notes} from 'apps'
+
+const appList = {
+ Notes,
+};
+
+const Home = () => {
+ const [apps, setApps] = useState([])
+ const {mutateUser} = useUser({
+ redirectToLogin: true,
+ redirectToVerify: true,
+ redirectToApps: true,
+ })
+
+ return (
+ <Layout apps={apps} setApps={setApps}>
+ <>
+ {
+ Object.keys(appList).map(appName => (
+ <div key={`${appName}_icon`} onClick={() => open(appName, apps, setApps)}>
+ <img src={`./${appName.toLowerCase()}.svg`} alt={`${appName} Icon`} />
+ <p>{appName}</p>
+ </div>
+ ))
+ }
+ { apps && apps.map(app => {
+ const AppName = appList[app.name]
+
+ return (
+ <App
+ key={`${app.name}_app`}
+ app={app}
+ apps={apps}
+ setApps={setApps}
+ >
+ <AppName />
+ </App>
+ );
+ })}
+ <style jsx>{`
+ div {
+ text-decoration: none;
+ display: inline-block;
+ width: 4em;
+ cursor: pointer;
+ }
+
+ img {
+ width: 4em;
+ }
+
+ p {
+ padding-top: .5em;
+ text-align: center;
+ color: #333;
+ }
+ `}</style>
+ </>
+ </Layout>
+ )
+}
+
+export default Home
diff --git a/pages/login.js b/pages/login.js
new file mode 100644
index 0000000..3fb2df6
--- /dev/null
+++ b/pages/login.js
@@ -0,0 +1,26 @@
+import { useState } from 'react'
+import useUser from 'lib/useUser'
+import submitForm from 'helpers/submitForm'
+import {Layout, Form} from 'components'
+
+const Login = () => {
+ const {mutateUser} = useUser({
+ redirectToVerify: true,
+ redirectToApps: true,
+ })
+
+ const [errorMsg, setErrorMsg] = useState('')
+ const handleSubmit = e => submitForm(e, '/api/login', mutateUser, setErrorMsg)
+
+ return (
+ <Layout>
+ <Form
+ isLogin
+ errorMessage={errorMsg}
+ onSubmit={handleSubmit}
+ />
+ </Layout>
+ )
+}
+
+export default Login
diff --git a/pages/register.js b/pages/register.js
new file mode 100644
index 0000000..3a00504
--- /dev/null
+++ b/pages/register.js
@@ -0,0 +1,24 @@
+import {useState } from 'react'
+import useUser from 'lib/useUser'
+import submitForm from 'helpers/submitForm'
+import {Layout, Form} from 'components'
+
+const Register = () => {
+ const { mutateUser } = useUser({
+ redirectToVerify: true,
+ })
+
+ const [errorMsg, setErrorMsg] = useState('')
+ const handleSubmit = e => submitForm(e, '/api/register', mutateUser, setErrorMsg)
+
+ return (
+ <Layout>
+ <Form
+ errorMessage={errorMsg}
+ onSubmit={handleSubmit}
+ />
+ </Layout>
+ )
+}
+
+export default Register
diff --git a/pages/verify.js b/pages/verify.js
new file mode 100644
index 0000000..1d89e22
--- /dev/null
+++ b/pages/verify.js
@@ -0,0 +1,109 @@
+import {useState, useEffect} from 'react'
+import {useRouter} from 'next/router'
+import useUser from 'lib/useUser'
+import fetchJson from 'lib/fetchJson'
+import {Layout} from 'components'
+
+const Verify = () => {
+ const router = useRouter()
+ const {user, mutateUser} = useUser({
+ redirectToLogin: true,
+ redirectToApps: true,
+ })
+ const [errorMsg, setErrorMsg] = useState('')
+ const [sending, setSending] = useState(false)
+ const [resent, setResent] = useState(false)
+
+ const handleSendMail = async e => {
+ e.preventDefault()
+ setErrorMsg('')
+ setSending(true)
+ try {
+ await fetch('/api/verify')
+ setResent(true)
+ } catch (error) {
+ setErrorMsg('Could not send verification email')
+ } finally {
+ setSending(false)
+ }
+ }
+
+ const handleKey = async e => {
+ e.preventDefault()
+ const key = e.currentTarget.key.value
+ try {
+ mutateUser(
+ await fetchJson('/api/verify', {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify({_id: user._id, key}),
+ })
+ )
+ } catch (err) {
+ setErrorMsg('Could not verify user')
+ }
+ }
+
+ return (
+ <Layout>
+ {!user
+ ? (
+ <div className="window window--popup">
+ <p>Loading...</p>
+ </div>
+ ) : (
+ <div className="window window--popup">
+ <p>One last step missing</p>
+ <p>{`To start using Notes App type the verification code we sent to your email (${user.email}):`}</p>
+ <form onSubmit={handleKey}>
+ <input type="text" placeholder="Verification key" name="key" />
+ <button className="window__button" type="submit">Send</button>
+ </form>
+ {
+ sending
+ ? (
+ <p>Sending...</p>
+ ) : (
+ resent
+ ? (
+ <p>Mail was successfully sent again, check your mailbox!</p>
+ ) : (
+ <p>If you didn't get verification email&nbsp;
+ <span className="verify__sendEmail" onClick={handleSendMail}>send it again</span>.
+ </p>
+ )
+ )
+ }
+ {errorMsg && <p className="verify__errorMsg">{errorMsg}</p>}
+ </div>
+ )
+ }
+ <style jsx>{`
+ form {
+ padding .5em 0;
+ }
+
+ input {
+ padding: .75em;
+ border: 1px dashed #333;
+ border-radius: .5em;
+ }
+
+ p {
+ line-height: 1.33;
+ padding: .5em 0;
+ }
+
+ .verify__sendEmail {
+ color: blue;
+ cursor: pointer;
+ }
+ .verify__errorMsg {
+ color: brown;
+ }
+ `}</style>
+ </Layout>
+ )
+}
+
+export default Verify