mirror of
https://gitea.smigz.com/smiggiddy/odin-codeprojects.git
synced 2025-04-04 11:00:58 -04:00
feat: app is complete however needs styling
This commit is contained in:
parent
05411c6bbb
commit
9d0787a5e8
18 changed files with 525 additions and 51 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1,3 +1,4 @@
|
|||
*.db-*
|
||||
*.db
|
||||
# Logs
|
||||
logs
|
||||
|
|
|
@ -75,10 +75,44 @@ h6 {
|
|||
isolation: isolate;
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
nav {
|
||||
font-size: 1.5rem;
|
||||
margin: 1em 0 2em;
|
||||
}
|
||||
|
||||
nav > ul {
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
ul {
|
||||
padding: 0;
|
||||
margin: auto;
|
||||
justify-content: space-around;
|
||||
max-width: 80vw;
|
||||
}
|
||||
|
||||
ul > li {
|
||||
display: inline-block;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
form {
|
||||
width: 100%;
|
||||
max-width: 50vw;
|
||||
}
|
||||
|
||||
.flex {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.col {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.container.flex.hero {
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
@ -98,6 +132,14 @@ h6 {
|
|||
padding: 1em;
|
||||
}
|
||||
|
||||
.center-horizontal {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.hero__heading {
|
||||
margin: 0;
|
||||
font-size: var(--mobile-heading-font-size);
|
||||
|
@ -138,7 +180,84 @@ h6 {
|
|||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.feed-heading {
|
||||
margin-left: 1em;
|
||||
text-transform: capitalize;
|
||||
}
|
||||
|
||||
.feed-heading span {
|
||||
text-transform: initial;
|
||||
}
|
||||
|
||||
.grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
|
||||
gap: 1em;
|
||||
padding: 2em;
|
||||
grid-auto-flow: dense;
|
||||
}
|
||||
|
||||
.grid-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.grid-item.card {
|
||||
border: 1px solid black;
|
||||
text-align: center;
|
||||
padding: 1.5em 1.5em 0.5em;
|
||||
}
|
||||
|
||||
.grid__card__metadata {
|
||||
font-size: 0.8em;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.card .card__message {
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
.form-item {
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/*.active__underline {*/
|
||||
/**/
|
||||
/*}*/
|
||||
|
||||
.hover__underline {
|
||||
/*display: inline-block;*/
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.red {
|
||||
color: red;
|
||||
}
|
||||
|
||||
.hover__underline::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
transform: scaleX(0);
|
||||
height: 2px;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
background-color: black;
|
||||
transform-origin: bottom left;
|
||||
transition: transform 0.25s ease-out;
|
||||
}
|
||||
|
||||
.hover__underline:hover::after {
|
||||
transform: scaleX(1);
|
||||
transform-origin: bottom left;
|
||||
}
|
||||
|
||||
@media only screen and (min-width: 750px) {
|
||||
ul {
|
||||
max-width: 60vw;
|
||||
}
|
||||
.hero__heading {
|
||||
margin: 0;
|
||||
font-size: var(--desktop-heading-font-size);
|
||||
|
@ -159,8 +278,11 @@ h6 {
|
|||
#main > .container.flex {
|
||||
gap: 10em;
|
||||
}
|
||||
|
||||
.form-item > .btn {
|
||||
max-width: 200px;
|
||||
.grid__span_two {
|
||||
grid-column-end: span 2;
|
||||
}
|
||||
|
||||
/*.form-item > .btn {*/
|
||||
/* max-width: 200px;*/
|
||||
/*}*/
|
||||
}
|
||||
|
|
BIN
keynotes.app/public/images/favicon.png
Normal file
BIN
keynotes.app/public/images/favicon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.2 KiB |
0
keynotes.app/public/js/script.js
Normal file
0
keynotes.app/public/js/script.js
Normal file
|
@ -1,9 +1,9 @@
|
|||
const bcryptjs = require("bcryptjs");
|
||||
const db = require("../models/db");
|
||||
const passport = require("../middlewares/auth");
|
||||
const db = require("../models/query");
|
||||
const { validationResult } = require("express-validator");
|
||||
|
||||
function loginGet(req, res, next) {
|
||||
res.render("login", { pageTitle: "KeyNotes.App | Login" });
|
||||
res.render("login", { pageTitle: "InspiredCliches | Login" });
|
||||
}
|
||||
|
||||
function logOut(req, res, next) {
|
||||
|
@ -14,20 +14,24 @@ function logOut(req, res, next) {
|
|||
}
|
||||
|
||||
function signUpGet(req, res, next) {
|
||||
res.render("register", { pageTitle: "KeyNotes.App | Register" });
|
||||
res.render("register", {
|
||||
pageTitle: "InspiredCliches | Register",
|
||||
errors: null,
|
||||
});
|
||||
}
|
||||
|
||||
async function signUpPost(req, res, next) {
|
||||
const { username, password } = req.body;
|
||||
try {
|
||||
const result = validationResult(req);
|
||||
if (result.isEmpty()) {
|
||||
const { username, password } = req.body;
|
||||
const hashedPassword = await bcryptjs.hash(password, 10);
|
||||
const query = db.query(
|
||||
"INSERT INTO users (username, password) VALUES ($username, $password)",
|
||||
);
|
||||
query.run({ $username: username, $password: hashedPassword });
|
||||
res.redirect("/");
|
||||
} catch (err) {
|
||||
next(err);
|
||||
db.insertUser(username, hashedPassword);
|
||||
res.redirect("/auth/login");
|
||||
} else {
|
||||
res.status(400).render("register", {
|
||||
errors: result.array(),
|
||||
pageTitle: "InspiredCliches | Register",
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,11 +1,74 @@
|
|||
const db = require("../models/query");
|
||||
|
||||
function indexGet(req, res, next) {
|
||||
if (res.locals.currentUser) {
|
||||
res.send(
|
||||
`Thanks for stopping by ${res.locals.currentUser.username.toUpperCase()}<br><a href='/auth/logout'>Log Out</a>`,
|
||||
);
|
||||
const keynotes = db.getEveryNote();
|
||||
const userLikedPosts = db.getLikesByUser(res.locals.currentUser.user_id);
|
||||
|
||||
res.render("feed", {
|
||||
pageTitle: "InspiredCliches | Feed",
|
||||
keynotes: keynotes,
|
||||
userLikedPosts: userLikedPosts,
|
||||
});
|
||||
}
|
||||
res.render("home", { pageTitle: "KeyNotes.App" });
|
||||
res.render("home", { pageTitle: "InspiredCliches" });
|
||||
}
|
||||
|
||||
function addLike(req, res, next) {
|
||||
const { noteId } = req.query;
|
||||
|
||||
const noteExits = noteId ? db.getNoteById(noteId) : null;
|
||||
|
||||
if (res.locals.currentUser && noteExits) {
|
||||
const userId = res.locals.currentUser.user_id;
|
||||
if (db.checkIfNotedLiked(noteId, userId)) {
|
||||
db.deleteLike(noteId, userId);
|
||||
} else {
|
||||
db.insertLike(Number(noteId), userId);
|
||||
}
|
||||
}
|
||||
res.redirect("/");
|
||||
}
|
||||
|
||||
function addNotePost(req, res, next) {
|
||||
const { message, media } = req.body;
|
||||
|
||||
if (res.locals.currentUser) {
|
||||
const userId = res.locals.currentUser.user_id;
|
||||
|
||||
db.putNewNote({ message: message, media: null, userId: userId });
|
||||
}
|
||||
|
||||
res.redirect("/");
|
||||
}
|
||||
|
||||
function addNoteGet(req, res, next) {
|
||||
res.render("note-form", { pageTitle: "InspiredCliches | New Note" });
|
||||
}
|
||||
|
||||
function getProfile(req, res, next) {
|
||||
const { userId } = req.query;
|
||||
|
||||
const userExists = userId ? db.getUserById(userId) : null;
|
||||
|
||||
if (res.locals.currentUser) {
|
||||
if (userExists) {
|
||||
const sumUserPosts = db.getAllNotesByUserId(userId);
|
||||
res.render("view-profile", {
|
||||
pageTitle: "InspiredCliches | Edit Profile",
|
||||
user: userExists,
|
||||
totalPosts: sumUserPosts,
|
||||
});
|
||||
} else {
|
||||
res.redirect("/");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
indexGet,
|
||||
addNoteGet,
|
||||
addNotePost,
|
||||
addLike,
|
||||
getProfile,
|
||||
};
|
||||
|
|
|
@ -20,6 +20,8 @@ stat(dbDirPath, (err, stats) => {
|
|||
});
|
||||
|
||||
const db = new Database(dbPath);
|
||||
// Enable WAL Mode
|
||||
db.exec("PRAGMA journal_mode = WAL;");
|
||||
|
||||
const initSQL = path.join(__dirname, "./init.sql");
|
||||
fs.readFile(initSQL, "utf8", (err, data) => {
|
||||
|
@ -27,7 +29,7 @@ fs.readFile(initSQL, "utf8", (err, data) => {
|
|||
console.error(err);
|
||||
return;
|
||||
}
|
||||
db.query(data).get();
|
||||
db.exec(data);
|
||||
});
|
||||
|
||||
module.exports = db;
|
||||
|
|
|
@ -1,5 +1,73 @@
|
|||
CREATE TABLE IF NOT EXISTS users (
|
||||
user_id INTEGER PRIMARY KEY ASC,
|
||||
username VARCHAR(50),
|
||||
password TEXT
|
||||
username VARCHAR(50) UNIQUE NOT NULL,
|
||||
password TEXT NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS user_profile_info (
|
||||
user_info_id INTEGER PRIMARY KEY ASC,
|
||||
email VARCHAR(50),
|
||||
user_id INTEGER REFERENCES users(user_id)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS messages (
|
||||
message_id INTEGER PRIMARY KEY ASC,
|
||||
message TEXT,
|
||||
media VARCHAR(100),
|
||||
date NUMBER,
|
||||
user_id INTEGER REFERENCES users(user_id)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS likes (
|
||||
likes_id INTEGER PRIMARY KEY ASC,
|
||||
message_id INTEGER REFERENCES messages(message_id),
|
||||
user_id INTEGER REFERENCES users(user_id),
|
||||
liked_at NUMBER
|
||||
);
|
||||
|
||||
|
||||
|
||||
INSERT OR IGNORE INTO users (username, password)
|
||||
VALUES ("jim", "$2a$10$Bmjre5WSpSSAi.nWBfLZFOlhQhbIAoY/MM7ikJz3Ho9tqeXCExaB6"),
|
||||
("demo", "$2a$10$Vo.XmsVQVx9gGojRIdewpOap5SnhrgZ21/Im5IxhH3PC4FycM5uwC");
|
||||
|
||||
INSERT OR REPLACE INTO messages (message_id, message, media, date, user_id)
|
||||
VALUES
|
||||
(1, "When life gives you lemons, make lemonade.", NULL, strftime('%s', 'now'), 1),
|
||||
(2, "Rome wasn’t built in a day – take your time.", NULL, strftime('%s', 'now'), 1),
|
||||
(3, "The grass is always greener on the other side.", NULL, strftime('%s', 'now'), 1),
|
||||
(4, "If it ain’t broke, don’t fix it.", NULL, strftime('%s', 'now'), 1),
|
||||
(5, "You can’t have your cake and eat it too.", NULL, strftime('%s', 'now'), 1),
|
||||
(6, "Better late than never.", NULL, strftime('%s', 'now'), 1),
|
||||
(7, "What doesn’t kill you makes you stronger.", NULL, strftime('%s', 'now'), 1),
|
||||
(8, "Every cloud has a silver lining.", NULL, strftime('%s', 'now'), 1),
|
||||
(9, "Don’t bite the hand that feeds you.", NULL, strftime('%s', 'now'), 1),
|
||||
(10, "Absence makes the heart grow fonder.", NULL, strftime('%s', 'now'), 1),
|
||||
(11, "Always trust your gut feeling – it’s usually right.", NULL, strftime('%s', 'now'), 2),
|
||||
(12, "Money can’t buy happiness, but it sure helps.", NULL, strftime('%s', 'now'), 2),
|
||||
(13, "Everything happens for a reason.", NULL, strftime('%s', 'now'), 2),
|
||||
(14, "Don’t go to bed angry – resolve conflicts before sleeping.", NULL, strftime('%s', 'now'), 2),
|
||||
(15, "The early bird catches the worm.", NULL, strftime('%s', 'now'), 2),
|
||||
(16, "You only live once – make the most of it.", NULL, strftime('%s', 'now'), 2),
|
||||
(17, "Hard work pays off in the end.", NULL, strftime('%s', 'now'), 2),
|
||||
(18, "Family is everything – cherish them.", NULL, strftime('%s', 'now'), 2),
|
||||
(19, "Don’t put off until tomorrow what you can do today.", NULL, strftime('%s', 'now'), 2),
|
||||
(20, "A smile costs nothing but gives so much.", NULL, strftime('%s', 'now'), 2),
|
||||
(21, "You can’t please everyone – focus on yourself.", NULL, strftime('%s', 'now'), 2),
|
||||
(22, "Health is wealth – take care of your body.", NULL, strftime('%s', 'now'), 2),
|
||||
(23, "Patience is a virtue – good things take time.", NULL, strftime('%s', 'now'), 2),
|
||||
(24, "Don’t judge a book by its cover.", NULL, strftime('%s', 'now'), 2),
|
||||
(25, "Actions speak louder than words.", NULL, strftime('%s', 'now'), 2),
|
||||
(26, "Learn from your mistakes – they make you wiser.", NULL, strftime('%s', 'now'), 2),
|
||||
(27, "Kindness costs nothing but means everything.", NULL, strftime('%s', 'now'), 2),
|
||||
(28, "Life is short – eat the cake.", NULL, strftime('%s', 'now'), 2),
|
||||
(29, "Comparison is the thief of joy – focus on your journey.", NULL, strftime('%s', 'now'), 2),
|
||||
(30, "The best things in life are free.", NULL, strftime('%s', 'now'), 2);
|
||||
|
||||
-- ALTER TABLE likes
|
||||
-- ADD COLUMN user_id INTEGER REFERENCES users(user_id);
|
||||
|
||||
-- ALTER TABLE likes
|
||||
-- ADD COLUMN liked_at NUMBER;
|
||||
|
||||
-- ALTER TABLE likes DROP COLUMN sum_likes;
|
||||
|
|
117
keynotes.app/src/models/query.js
Normal file
117
keynotes.app/src/models/query.js
Normal file
|
@ -0,0 +1,117 @@
|
|||
const db = require("./db");
|
||||
|
||||
function getEveryNote() {
|
||||
try {
|
||||
const query = db.query(
|
||||
`SELECT messages.message_id, message, media, date, users.username AS user, messages.user_id, COUNT(likes.likes_id) AS likes_count
|
||||
FROM messages LEFT JOIN users ON messages.user_id = users.user_id
|
||||
LEFT JOIN likes ON messages.message_id = likes.message_id
|
||||
GROUP BY messages.message_id, message, media, date, users.username
|
||||
`,
|
||||
);
|
||||
|
||||
const data = query.all();
|
||||
console.log(data);
|
||||
return data;
|
||||
} catch (err) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
function putNewNote(note) {
|
||||
const { message, media, userId } = note;
|
||||
const date = Date.now();
|
||||
const query = db.query(
|
||||
`INSERT INTO messages (message, media, user_id, date) VALUES ($1, $2, $3, $4)`,
|
||||
);
|
||||
query.run({ $1: message, $2: media, $3: userId, $4: date });
|
||||
}
|
||||
|
||||
function getLikesByUser(userId) {
|
||||
const query = db.query(`SELECT message_id FROM likes WHERE user_id = $1`);
|
||||
|
||||
return query.all({ $1: userId });
|
||||
}
|
||||
|
||||
function getTotalLikesByMessageId(messageId) {
|
||||
const query = db.query(`SELECT COUNT(1) FROM likes WHERE message_id = $1`);
|
||||
return query.get({ $1: messageId });
|
||||
}
|
||||
|
||||
function getNoteById(noteId) {
|
||||
const query = db.query(`SELECT message from messages WHERE message_id = $1`);
|
||||
return query.get({ $1: noteId });
|
||||
}
|
||||
|
||||
function checkIfNotedLiked(messageId, userId) {
|
||||
const query = db.query(
|
||||
`SELECT * FROM likes WHERE message_id = $1 and user_id = $2`,
|
||||
);
|
||||
|
||||
const res = query.get({ $1: messageId, $2: userId });
|
||||
return res;
|
||||
}
|
||||
|
||||
function insertLike(messageId, userId) {
|
||||
try {
|
||||
const query = db.query(
|
||||
`INSERT INTO likes (message_id, user_id, liked_at) VALUES ($1, $2, $3)`,
|
||||
);
|
||||
query.run({ $1: messageId, $2: userId, $3: Date.now() });
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
function deleteLike(messageId, userId) {
|
||||
try {
|
||||
const query = db.query(
|
||||
`DELETE FROM likes WHERE message_id = $1 and user_id = $2`,
|
||||
);
|
||||
query.run({ $1: messageId, $2: userId });
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
function insertUser(username, password) {
|
||||
try {
|
||||
const query = db.query(
|
||||
"INSERT INTO users (username, password) VALUES ($username, $password)",
|
||||
);
|
||||
query.run({ $username: username, $password: password });
|
||||
} catch (err) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
function getUserById(userId) {
|
||||
const query = db.query(
|
||||
`SELECT username, user_id FROM users WHERE user_id = $1`,
|
||||
);
|
||||
const res = query.get({ $1: userId });
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
function getAllNotesByUserId(userId) {
|
||||
const query = db.query(`SELECT COUNT(1) FROM messages WHERE user_id = $1`);
|
||||
const res = query.get({ $1: userId });
|
||||
|
||||
return res["COUNT(1)"];
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
getEveryNote,
|
||||
getNoteById,
|
||||
putNewNote,
|
||||
insertLike,
|
||||
deleteLike,
|
||||
checkIfNotedLiked,
|
||||
insertUser,
|
||||
getLikesByUser,
|
||||
getTotalLikesByMessageId,
|
||||
getUserById,
|
||||
getAllNotesByUserId,
|
||||
};
|
|
@ -1,6 +1,7 @@
|
|||
const { Router } = require("express");
|
||||
const authController = require("../controllers/authController");
|
||||
const passport = require("../middlewares/auth");
|
||||
const { body } = require("express-validator");
|
||||
|
||||
const authRouter = Router();
|
||||
|
||||
|
@ -15,6 +16,16 @@ authRouter.post(
|
|||
);
|
||||
authRouter.get("/logout", authController.logOut);
|
||||
authRouter.get("/register", authController.signUpGet);
|
||||
authRouter.post("/register", authController.signUpPost);
|
||||
authRouter.post(
|
||||
"/register",
|
||||
body("password").isLength({ min: 5 }).withMessage("Password is too short"),
|
||||
body("confirm-password").custom((value, { req }) => {
|
||||
if (value !== req.body.password) {
|
||||
throw new Error("Passwords do not match!");
|
||||
}
|
||||
return true;
|
||||
}),
|
||||
authController.signUpPost,
|
||||
);
|
||||
|
||||
module.exports = { authRouter };
|
||||
|
|
|
@ -4,5 +4,9 @@ const indexController = require("../controllers/indexController");
|
|||
const indexRouter = Router();
|
||||
|
||||
indexRouter.get("/", indexController.indexGet);
|
||||
indexRouter.get("/like", indexController.addLike);
|
||||
indexRouter.get("/new", indexController.addNoteGet);
|
||||
indexRouter.post("/new", indexController.addNotePost);
|
||||
indexRouter.get("/profile", indexController.getProfile);
|
||||
|
||||
module.exports = { indexRouter };
|
||||
|
|
27
keynotes.app/src/views/feed.ejs
Normal file
27
keynotes.app/src/views/feed.ejs
Normal file
|
@ -0,0 +1,27 @@
|
|||
<%- include('header') %>
|
||||
<h1 class="feed-heading">
|
||||
<%= currentUser.username %>'s <span class="normal">feed of cliche's</span>
|
||||
</h1>
|
||||
<div class="grid">
|
||||
<% keynotes.forEach((note) => { %>
|
||||
<% const likedPost = userLikedPosts.find((post) => post.message_id == note.message_id) %>
|
||||
<% let extraMessageClass = "" %>
|
||||
<% if (note.message.length > 250) { %>
|
||||
<% extraMessageClass = " grid__span_two"; %>
|
||||
<% }; %>
|
||||
<div class="grid-item card<%= extraMessageClass %>">
|
||||
<p class="card__message"><%= note.message %></p>
|
||||
<div class="container flex grid__card__metadata">
|
||||
<p class="card__author"><a href="/profile?userId=<%= note.user_id %>"><%= note.user %></a></p>
|
||||
<p><%= note.likes_count %> Likes</p>
|
||||
<a href="/like?noteId=<%= note.message_id %>">
|
||||
<% if (likedPost) { %><i class="fa-solid fa-heart red"></i><% } else { %><i class="fa-regular fa-heart red"></i><% }; %>
|
||||
</a>
|
||||
<% if (currentUser.user_id === note.user_id) { %>
|
||||
<a href="#"> Delete</a>
|
||||
<% }; %>
|
||||
</div>
|
||||
</div>
|
||||
<% }); %>
|
||||
</div>
|
||||
<%- include('footer') %>
|
|
@ -1,2 +1,3 @@
|
|||
<script src="/js/script.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -9,6 +9,21 @@
|
|||
<link href="https://fonts.googleapis.com/css2?family=Lato:ital,wght@0,100;0,300;0,400;0,700;0,900;1,100;1,300;1,400;1,700;1,900&family=Rokkitt:ital,wght@0,100..900;1,100..900&display=swap" rel="stylesheet">
|
||||
<title><%= pageTitle %></title>
|
||||
<link href="/css/style.css" rel="stylesheet">
|
||||
<link rel="icon" href="/images/favicon.png">
|
||||
<!--<script src="https://kit.fontawesome.com/24f16b96cf.js" crossorigin="anonymous"></script>-->
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/js/all.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<nav>
|
||||
<ul class="container flex">
|
||||
<li><a class="hover__underline" href="/">Home</a></li>
|
||||
<% if (currentUser) { %>
|
||||
<li><a class="hover__underline" href="/new" class="new-link">New Note</a></li>
|
||||
<li><a class="hover__underline" href="/profile?userId=<%= currentUser.user_id %>">Profile</a></li>
|
||||
<li><a class="hover__underline" href="/auth/logout">Logout</a></li>
|
||||
<% } else { %>
|
||||
<li><a class="hover__underline" href="/auth/login">Login</a></li>
|
||||
<% }; %>
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
|
|
|
@ -1,20 +1,17 @@
|
|||
<%- include('header') %>
|
||||
<form method="POST" action="/auth/login">
|
||||
<div class="container">
|
||||
<div class="form-item flex">
|
||||
<form class="center-horizontal" method="POST" action="/auth/login">
|
||||
<div class="form-item flex">
|
||||
<label for="username">UserName</label>
|
||||
<input type="text" name="username"/>
|
||||
</div>
|
||||
<div class="form-item flex">
|
||||
<label for="password">Password</label>
|
||||
<input type="password" name="password"/>
|
||||
</div>
|
||||
<div class="form-item">
|
||||
<button type="submit" class="btn">Login</button>
|
||||
<button type="button" class="btn">Sign in with Google</button>
|
||||
<button type="button" class="btn" onclick="document.location.href='/auth/register'">Sign Up</button>
|
||||
</div>
|
||||
<input type="text" name="username" required/>
|
||||
</div>
|
||||
<div class="form-item flex">
|
||||
<label for="password">Password</label>
|
||||
<input type="password" name="password" required/>
|
||||
</div>
|
||||
<div class="form-item flex">
|
||||
<button type="submit" class="btn">Login</button>
|
||||
<button type="button" class="btn" onclick="document.location.href='/auth/register'">Sign up</button>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
<%- include('footer') %>
|
||||
|
|
19
keynotes.app/src/views/note-form.ejs
Normal file
19
keynotes.app/src/views/note-form.ejs
Normal file
|
@ -0,0 +1,19 @@
|
|||
<%- include("header") %>
|
||||
<form action="/new" method="POST" class="center-horizontal">
|
||||
<div class="form-item flex">
|
||||
<label for="message">Message</label>
|
||||
<input type="text" name="message" required/>
|
||||
</div>
|
||||
<div class="form-item flex">
|
||||
<label for="media">Media</label>
|
||||
<input type="text" name="media" />
|
||||
</div>
|
||||
<div class="form-item flex col">
|
||||
<button type="submit" class="btn">Post</button>
|
||||
<button type="button" class="btn" onClick="document.location.href='/'">Back</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
|
||||
|
||||
<%- include("footer") %>
|
|
@ -1,19 +1,30 @@
|
|||
<%- include('header') %>
|
||||
<form method="POST" action="/auth/register">
|
||||
<div class="container">
|
||||
<div class="form-item flex">
|
||||
<!-- views/partials/errors.ejs -->
|
||||
<% if (locals.errors) {%>
|
||||
<div class="center-horizontal">
|
||||
<ul>
|
||||
<% errors.forEach(function(error) { %>
|
||||
<li><%= error.msg %></li>
|
||||
<% }); %>
|
||||
</ul>
|
||||
</div>
|
||||
<% }; %>
|
||||
<form class="register-form center-horizontal" method="POST" action="/auth/register">
|
||||
<div class="form-item flex">
|
||||
<label for="username">UserName</label>
|
||||
<input type="text" name="username"/>
|
||||
</div>
|
||||
<div class="form-item flex">
|
||||
<label for="password">Password</label>
|
||||
<input type="password" name="password"/>
|
||||
</div>
|
||||
<div class="form-item">
|
||||
<button type="submit" class="btn">Register</button>
|
||||
<button type="button" class="btn">Sign up with Google</button>
|
||||
</div>
|
||||
<input type="text" name="username" required/>
|
||||
</div>
|
||||
<div class="form-item flex">
|
||||
<label for="password">Password</label>
|
||||
<input type="password" name="password" required/>
|
||||
</div>
|
||||
<div class="form-item flex">
|
||||
<label for="confirm-password">Confirm Password</label>
|
||||
<input type="password" name="confirm-password" required/>
|
||||
</div>
|
||||
<div class="form-item flex">
|
||||
<button type="submit" class="btn">Register</button>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
<%- include('footer') %>
|
||||
|
|
12
keynotes.app/src/views/view-profile.ejs
Normal file
12
keynotes.app/src/views/view-profile.ejs
Normal file
|
@ -0,0 +1,12 @@
|
|||
<%- include("header") %>
|
||||
|
||||
<div class="container flex center-horizontal">
|
||||
<h1 class="username"><%= user.username %></h1>
|
||||
<h2 class="email"><%= user.user_email %></h2>
|
||||
<p><%= totalPosts %> Posts</p>
|
||||
|
||||
<% if(currentUser.user_id === user.user_id ) { %>
|
||||
This is your profile page.
|
||||
<% }; %>
|
||||
</div>
|
||||
<%- include("footer") %>
|
Loading…
Add table
Reference in a new issue