Compare commits
4 Commits
5c769bfa2f
...
main
Author | SHA1 | Date | |
---|---|---|---|
92960c4fa7 | |||
f8559b477b | |||
cb529e47d9 | |||
dabd5ea0f0 |
695
api/package-lock.json
generated
695
api/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -19,6 +19,7 @@
|
||||
"format": "npx prettier --write ."
|
||||
},
|
||||
"dependencies": {
|
||||
"bcrypt": "^5.1.1",
|
||||
"colors": "1.4.0",
|
||||
"cookie-parser": "^1.4.5",
|
||||
"cors": "^2.8.5",
|
||||
@@ -33,6 +34,7 @@
|
||||
"sequelize": "^6.15.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/bcrypt": "^5.0.2",
|
||||
"@types/cookie-parser": "^1.4.2",
|
||||
"@types/cors": "^2.8.10",
|
||||
"@types/ejs": "^3.0.6",
|
||||
@@ -46,6 +48,7 @@
|
||||
"@types/shelljs": "^0.8.9",
|
||||
"jest": "^27.0.6",
|
||||
"morgan": "^1.10.0",
|
||||
"nodemon": "^3.0.2",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"rimraf": "^3.0.2",
|
||||
"shelljs": "^0.8.4",
|
||||
|
@@ -1,13 +1,21 @@
|
||||
import env from './environment'
|
||||
import { Err, Succ } from '../services/globalService'
|
||||
import db from './sequelize.config'
|
||||
import Client from '../models/Client'
|
||||
import Project from '../models/Project'
|
||||
import Task from '../models/Task'
|
||||
import User from '../models/User'
|
||||
|
||||
function connect() {
|
||||
async function connect() {
|
||||
if (!env.NORK.database) {
|
||||
new Err(500, 'no database is in norkcfg.json')
|
||||
return false
|
||||
}
|
||||
if (env.NORK.database.orm == 'sequelize') {
|
||||
await User.sync()
|
||||
await Client.sync()
|
||||
await Project.sync()
|
||||
await Task.sync({ alter: true })
|
||||
db.sync()
|
||||
.then(() => {
|
||||
new Succ(200, 'connected to db')
|
||||
|
@@ -1,5 +1,6 @@
|
||||
import { Request, Response } from 'express'
|
||||
import Task from '../models/Task'
|
||||
import { Err, Succ } from '../services/globalService'
|
||||
|
||||
export async function get(req: Request, res: Response) {
|
||||
try {
|
||||
@@ -11,9 +12,34 @@ export async function get(req: Request, res: Response) {
|
||||
}
|
||||
export async function add(req: Request, res: Response) {
|
||||
try {
|
||||
const task = await Task.create(req.body)
|
||||
const payload = req.body
|
||||
payload.author_id = res.locals.user._id
|
||||
console.log(payload)
|
||||
const task = await Task.create(payload)
|
||||
res.json(task)
|
||||
} catch (error) {
|
||||
res.status(500).send(error)
|
||||
}
|
||||
}
|
||||
|
||||
export async function edit(req: Request, res: Response) {
|
||||
try {
|
||||
const payload = req.body
|
||||
payload.author_id = res.locals.user._id
|
||||
const task: any = await Task.findByPk(payload._id)
|
||||
|
||||
if (!task) {
|
||||
return res.status(400).json(new Err(400, 'Task not found'))
|
||||
}
|
||||
|
||||
task.title = payload.title
|
||||
task.timeEnd = payload.timeEnd
|
||||
task.timeStart = payload.timeStart
|
||||
|
||||
await task.save()
|
||||
|
||||
return res.json(new Succ(200, 'Task updated succesfully'))
|
||||
} catch (error) {
|
||||
return res.status(500).json(new Err(400, 'something went wrong', error))
|
||||
}
|
||||
}
|
||||
|
76
api/src/controllers/userController.ts
Normal file
76
api/src/controllers/userController.ts
Normal file
@@ -0,0 +1,76 @@
|
||||
import { Request, Response } from 'express'
|
||||
import bcrypt from 'bcrypt'
|
||||
import jwt from 'jsonwebtoken'
|
||||
import env from '../config/environment'
|
||||
import User from '../models/User'
|
||||
import { Err, Succ } from '../services/globalService'
|
||||
|
||||
export async function login(req: Request, res: Response) {}
|
||||
|
||||
export async function signup(req: Request, res: Response) {
|
||||
try {
|
||||
const payload = req.body
|
||||
|
||||
payload.password = await bcrypt.hash(payload.password, 12)
|
||||
const user = await User.create(payload)
|
||||
|
||||
res.status(201).json(new Succ(201, 'user was successfully signed up'))
|
||||
} catch (err: any) {
|
||||
new Err(500, err)
|
||||
res.status(500).json(new Err(500, 'something went wrong'))
|
||||
}
|
||||
}
|
||||
|
||||
export async function signin(req: Request, res: Response) {
|
||||
try {
|
||||
const payload = req.body
|
||||
|
||||
const user: any = await User.findOne({ where: { email: payload.email } })
|
||||
if (!user) {
|
||||
res.cookie('jwt', '', { httpOnly: true, maxAge: 0 })
|
||||
res.cookie('auth', false, { httpOnly: false, maxAge: 0 })
|
||||
res.status(401).json(new Err(401, 'email or password is wrong'))
|
||||
return
|
||||
}
|
||||
|
||||
if (await bcrypt.compare(payload.password, user.password)) {
|
||||
const maxAge = 3 * 24 * 60 * 60 // 3 days in seconds
|
||||
const createToken = (id: any) => {
|
||||
return jwt.sign({ id }, env.JWT_SECRET, {
|
||||
expiresIn: maxAge
|
||||
})
|
||||
}
|
||||
|
||||
const token = createToken(user._id)
|
||||
res.cookie('jwt', token, { httpOnly: true, maxAge: maxAge * 1000 })
|
||||
res.cookie('auth', true, { httpOnly: false, maxAge: maxAge * 1000 })
|
||||
|
||||
res.json(new Succ(200, 'user is logged in'))
|
||||
return
|
||||
}
|
||||
|
||||
res.cookie('jwt', '', { httpOnly: true, maxAge: 0 })
|
||||
res.cookie('auth', false, { httpOnly: false, maxAge: 0 })
|
||||
res.status(401).json(new Err(401, 'email or password is wrong'))
|
||||
} catch (err: any) {
|
||||
new Err(500, err)
|
||||
res.status(500).json(new Err(500, 'something went wrong'))
|
||||
}
|
||||
}
|
||||
|
||||
export function logout(req: Request, res: Response) {
|
||||
res.cookie('jwt', '', { httpOnly: true, maxAge: 0 })
|
||||
res.cookie('auth', false, { httpOnly: false, maxAge: 0 })
|
||||
res.json(new Succ(200, 'user was logged out'))
|
||||
}
|
||||
|
||||
export function status(req: Request, res: Response) {
|
||||
try {
|
||||
let userObject = res.locals.user
|
||||
userObject.password = undefined
|
||||
userObject.__v = undefined
|
||||
res.status(200).json(new Succ(200, 'user is logged in', userObject))
|
||||
} catch (error) {
|
||||
res.status(500).json(new Err(500, 'somehting went wrong', error))
|
||||
}
|
||||
}
|
@@ -6,7 +6,7 @@ import User from '../models/User' // uncomment this
|
||||
|
||||
export function requireAuth(req: Request, res: Response, next: NextFunction) {
|
||||
const token = req.cookies.jwt
|
||||
new Err(500, 'uncomment code in authMiddleware before using!')
|
||||
//new Err(500, 'uncomment code in authMiddleware before using!')
|
||||
if (token) {
|
||||
jwt.verify(token, env.JWT_SECRET, async (err: any, decodedToken: any) => {
|
||||
if (err) {
|
||||
@@ -14,25 +14,16 @@ export function requireAuth(req: Request, res: Response, next: NextFunction) {
|
||||
res.status(401).json(new Err(401, 'user is not authenticated'))
|
||||
}
|
||||
if (!err) {
|
||||
const user = (async () => {
|
||||
if (env.NORK.db.orm) {
|
||||
if (env.NORK.db.orm == 'sequelize') {
|
||||
return await User.findByPk(decodedToken.id)
|
||||
}
|
||||
if (env.NORK.db.orm == 'mongoose') {
|
||||
return await User.findById(decodedToken.id)
|
||||
}
|
||||
} else {
|
||||
return null
|
||||
}
|
||||
})()
|
||||
|
||||
const user = await User.findByPk(decodedToken.id)
|
||||
console.log('TADY', user)
|
||||
if (user === null) {
|
||||
console.log('1')
|
||||
res.status(401).json(new Err(401, 'user is not authenticated'))
|
||||
return
|
||||
}
|
||||
|
||||
res.locals.user = user
|
||||
console.log('2')
|
||||
new Succ(100, 'user is authenticated')
|
||||
next()
|
||||
}
|
||||
@@ -40,6 +31,7 @@ export function requireAuth(req: Request, res: Response, next: NextFunction) {
|
||||
}
|
||||
|
||||
if (!token) {
|
||||
console.log('3')
|
||||
res.status(401).json(new Err(401, 'user is not authenticated'))
|
||||
}
|
||||
}
|
||||
|
44
api/src/models/Client.ts
Normal file
44
api/src/models/Client.ts
Normal file
@@ -0,0 +1,44 @@
|
||||
import { DataTypes, Model } from 'sequelize'
|
||||
import path from 'path'
|
||||
import db from '../config/sequelize.config'
|
||||
import User from './User'
|
||||
|
||||
class Instance extends Model {}
|
||||
|
||||
Instance.init(
|
||||
{
|
||||
_id: {
|
||||
type: DataTypes.UUID,
|
||||
defaultValue: DataTypes.UUIDV4,
|
||||
primaryKey: true,
|
||||
allowNull: false,
|
||||
unique: true
|
||||
},
|
||||
name: {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: false
|
||||
},
|
||||
hourlyRate: {
|
||||
type: DataTypes.INTEGER,
|
||||
allowNull: true
|
||||
},
|
||||
contact: {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: true
|
||||
},
|
||||
author_id: {
|
||||
type: DataTypes.UUID,
|
||||
allowNull: false,
|
||||
references: {
|
||||
model: User,
|
||||
key: '_id'
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
sequelize: db,
|
||||
tableName: path.basename(__filename).split('.')[0].toLowerCase()
|
||||
}
|
||||
)
|
||||
|
||||
export default Instance
|
49
api/src/models/Project.ts
Normal file
49
api/src/models/Project.ts
Normal file
@@ -0,0 +1,49 @@
|
||||
import { DataTypes, Model } from 'sequelize'
|
||||
import path from 'path'
|
||||
import db from '../config/sequelize.config'
|
||||
import User from './User'
|
||||
import Client from './Client'
|
||||
|
||||
class Instance extends Model {}
|
||||
|
||||
Instance.init(
|
||||
{
|
||||
_id: {
|
||||
type: DataTypes.UUID,
|
||||
defaultValue: DataTypes.UUIDV4,
|
||||
primaryKey: true,
|
||||
allowNull: false,
|
||||
unique: true
|
||||
},
|
||||
name: {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: false
|
||||
},
|
||||
hourlyRate: {
|
||||
type: DataTypes.INTEGER,
|
||||
allowNull: true
|
||||
},
|
||||
client_id: {
|
||||
type: DataTypes.UUID,
|
||||
allowNull: false,
|
||||
references: {
|
||||
model: Client,
|
||||
key: '_id'
|
||||
}
|
||||
},
|
||||
author_id: {
|
||||
type: DataTypes.UUID,
|
||||
allowNull: false,
|
||||
references: {
|
||||
model: User,
|
||||
key: '_id'
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
sequelize: db,
|
||||
tableName: path.basename(__filename).split('.')[0].toLowerCase()
|
||||
}
|
||||
)
|
||||
|
||||
export default Instance
|
@@ -1,6 +1,9 @@
|
||||
import { DataTypes, Model } from 'sequelize'
|
||||
import path from 'path'
|
||||
import db from '../config/sequelize.config'
|
||||
import User from './User'
|
||||
import Client from './Client'
|
||||
import Project from './Project'
|
||||
|
||||
class Instance extends Model {}
|
||||
|
||||
@@ -14,14 +17,6 @@ Instance.init(
|
||||
unique: true
|
||||
},
|
||||
title: {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: false
|
||||
},
|
||||
client: {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: true
|
||||
},
|
||||
project: {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: true
|
||||
},
|
||||
@@ -32,6 +27,22 @@ Instance.init(
|
||||
timeEnd: {
|
||||
type: DataTypes.BIGINT,
|
||||
allowNull: true
|
||||
},
|
||||
project_id: {
|
||||
type: DataTypes.UUID,
|
||||
allowNull: true,
|
||||
references: {
|
||||
model: Project,
|
||||
key: '_id'
|
||||
}
|
||||
},
|
||||
author_id: {
|
||||
type: DataTypes.UUID,
|
||||
allowNull: false,
|
||||
references: {
|
||||
model: User,
|
||||
key: '_id'
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@@ -8,28 +8,29 @@ Instance.init(
|
||||
{
|
||||
_id: {
|
||||
type: DataTypes.UUID,
|
||||
defaultValue: DataTypes.UUIDV4,
|
||||
primaryKey: true,
|
||||
allowNull: false,
|
||||
unique: true,
|
||||
unique: true
|
||||
},
|
||||
username: {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: false,
|
||||
allowNull: false
|
||||
},
|
||||
password: {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: false,
|
||||
allowNull: false
|
||||
},
|
||||
email: {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: false,
|
||||
unique: true,
|
||||
},
|
||||
unique: true
|
||||
}
|
||||
},
|
||||
{
|
||||
sequelize: db,
|
||||
tableName: path.basename(__filename).split('.')[0].toLowerCase(),
|
||||
},
|
||||
tableName: path.basename(__filename).split('.')[0].toLowerCase()
|
||||
}
|
||||
)
|
||||
|
||||
export default Instance
|
||||
|
@@ -1,8 +1,16 @@
|
||||
import { Router } from 'express'
|
||||
import * as taskController from "../controllers/taskController"
|
||||
import * as taskController from '../controllers/taskController'
|
||||
import * as userController from '../controllers/userController'
|
||||
import { requireAuth } from '../middlewares/authMiddleware'
|
||||
|
||||
export const router = Router()
|
||||
//const mws = [handleValidation.handleValidationError]
|
||||
|
||||
router.get("/task/get", taskController.get)
|
||||
router.post("/task/add", taskController.add)
|
||||
router.get('/task/get', requireAuth, taskController.get)
|
||||
router.post('/task/add', requireAuth, taskController.add)
|
||||
router.post('/task/edit', requireAuth, taskController.edit)
|
||||
|
||||
router.post('/auth/signup', userController.signup)
|
||||
router.post('/auth/signin', userController.signin)
|
||||
router.post('/auth/logout', requireAuth, userController.logout)
|
||||
router.get('/auth/status', requireAuth, userController.status)
|
||||
|
47
frontend/src/api/user.js
Normal file
47
frontend/src/api/user.js
Normal file
@@ -0,0 +1,47 @@
|
||||
const api_url = 'http://localhost:6060'
|
||||
const userAPIS = {
|
||||
async getUserStatus() {
|
||||
const res = await fetch(`${api_url}/api/v1/auth/status`, {
|
||||
credentials: 'include'
|
||||
})
|
||||
return res.json()
|
||||
},
|
||||
|
||||
async loginUser(formState) {
|
||||
const res = await fetch(`${api_url}/api/v1/auth/signin`, {
|
||||
method: 'POST',
|
||||
credentials: 'include',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify(formState)
|
||||
})
|
||||
return await res.json()
|
||||
},
|
||||
|
||||
async logoutUser() {
|
||||
const res = await fetch(`${api_url}/api/v1/auth/logout`, {
|
||||
method: 'POST',
|
||||
credentials: 'include',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({})
|
||||
})
|
||||
return await res.json()
|
||||
},
|
||||
|
||||
async registerUser(formState) {
|
||||
const res = await fetch(`${api_url}/api/v1/auth/signup`, {
|
||||
method: 'POST',
|
||||
credentials: 'include',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify(formState)
|
||||
})
|
||||
return res.json()
|
||||
}
|
||||
}
|
||||
|
||||
export default userAPIS
|
37
frontend/src/components/FormBase.vue
Normal file
37
frontend/src/components/FormBase.vue
Normal file
@@ -0,0 +1,37 @@
|
||||
<script setup>
|
||||
defineProps(['btn-txt', 'api-endpoint'])
|
||||
</script>
|
||||
<template>
|
||||
<form>
|
||||
<slot></slot>
|
||||
<button @click="formAction">{{ btnTxt }}</button>
|
||||
</form>
|
||||
</template>
|
||||
<script>
|
||||
import AppStore from '@/stores/AppStore'
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
d: {
|
||||
email: undefined,
|
||||
password: undefined,
|
||||
username: undefined
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
formAction() {
|
||||
console.log(this.d)
|
||||
//AppStore.sendAdd(null, this.$props.apiEndpoint)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
</style>
|
@@ -30,15 +30,16 @@ export default {
|
||||
timer: undefined,
|
||||
timerState: 'Start',
|
||||
task: {
|
||||
startTime: 0,
|
||||
stopTime: 0,
|
||||
timeStart: 0,
|
||||
timeEnd: 0,
|
||||
title: ''
|
||||
}
|
||||
},
|
||||
restore: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
formattedElapsedTime() {
|
||||
const date = new Date(this.timeNow - this.task.startTime)
|
||||
const date = new Date(this.timeNow - this.task.timeStart)
|
||||
const utc = date.toUTCString()
|
||||
return utc.substr(utc.indexOf(':') - 2, 8)
|
||||
}
|
||||
@@ -47,33 +48,60 @@ export default {
|
||||
async startStopTimer() {
|
||||
if (this.timerState == 'Start') {
|
||||
this.timerState = 'Stop'
|
||||
this.task.startTime = Date.now()
|
||||
console.log('TADY', this.restore)
|
||||
if (this.restore == false) {
|
||||
console.log('TADY')
|
||||
this.task.timeStart = Date.now()
|
||||
}
|
||||
this.timeNow = Date.now()
|
||||
console.log('timer started')
|
||||
this.timer = setInterval(() => {
|
||||
this.timeNow = Date.now()
|
||||
}, 1000)
|
||||
if (!this.task._id) {
|
||||
AppStore.data.newTask = {
|
||||
title: this.task.title,
|
||||
timeStart: this.task.timeStart
|
||||
}
|
||||
await AppStore.sendAdd(AppStore.data.newTask, '/task/add')
|
||||
}
|
||||
} else {
|
||||
this.task.stopTime = Date.now()
|
||||
this.task.timeEnd = Date.now()
|
||||
this.timerState = 'Start'
|
||||
clearInterval(this.timer)
|
||||
this.timer = undefined
|
||||
this.timeNow = 0
|
||||
|
||||
AppStore.data.newTask = {
|
||||
title: this.task.title,
|
||||
timeStart: this.task.startTime,
|
||||
timeEnd: this.task.stopTime
|
||||
timeStart: this.task.timeStart,
|
||||
timeEnd: this.task.timeEnd
|
||||
}
|
||||
if (this.task._id) {
|
||||
AppStore.data.newTask._id = this.task._id
|
||||
await AppStore.sendAdd(AppStore.data.newTask, '/task/edit')
|
||||
} else {
|
||||
await AppStore.sendAdd(AppStore.data.newTask, '/task/add')
|
||||
}
|
||||
await AppStore.sendAdd(AppStore.data.newTask, '/task/add')
|
||||
|
||||
this.task = {
|
||||
startTime: 0,
|
||||
stopTime: 0,
|
||||
timeStart: 0,
|
||||
timeEnd: 0,
|
||||
title: ''
|
||||
}
|
||||
this.restore = false
|
||||
this.$emit('get-tasks')
|
||||
}
|
||||
}
|
||||
},
|
||||
async mounted() {
|
||||
await AppStore.fetchData()
|
||||
const task = AppStore.data.fetchedTasks.filter((task) => task.timeEnd === null)
|
||||
if (task.length > 0) {
|
||||
this.task = task[0]
|
||||
this.restore = true
|
||||
this.startStopTimer()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
@@ -2,6 +2,14 @@ import { createRouter, createWebHistory } from 'vue-router'
|
||||
import TrackerView from '../views/TrackerView.vue'
|
||||
import SignupView from '../views/SignupView.vue'
|
||||
import LoginView from '../views/LoginView.vue'
|
||||
import userAPIS from '../api/user'
|
||||
|
||||
const authGuard = async () => {
|
||||
const data = await userAPIS.getUserStatus()
|
||||
if (!data.data) {
|
||||
throw router.push('/')
|
||||
}
|
||||
}
|
||||
|
||||
const router = createRouter({
|
||||
history: createWebHistory(import.meta.env.BASE_URL),
|
||||
@@ -10,7 +18,7 @@ const router = createRouter({
|
||||
path: '/',
|
||||
name: 'home',
|
||||
//component: HomeView
|
||||
redirect: '/tracker'
|
||||
redirect: '/tracker'
|
||||
},
|
||||
{
|
||||
path: '/login',
|
||||
@@ -26,7 +34,10 @@ const router = createRouter({
|
||||
path: '/tracker',
|
||||
name: 'tracker',
|
||||
component: TrackerView,
|
||||
alias: '/'
|
||||
alias: '/',
|
||||
meta: {
|
||||
requiresAuth: true
|
||||
}
|
||||
},
|
||||
{
|
||||
path: '/about',
|
||||
@@ -39,4 +50,20 @@ const router = createRouter({
|
||||
]
|
||||
})
|
||||
|
||||
router.beforeEach(async (to, from, next) => {
|
||||
const requiresAuth = to.matched.some((x) => x.meta.requiresAuth)
|
||||
const requiresGuest = to.matched.some((x) => x.meta.requiresGuest)
|
||||
|
||||
if (requiresAuth) {
|
||||
const userStatus = await userAPIS.getUserStatus()
|
||||
if (!userStatus.data) {
|
||||
router.replace('/login')
|
||||
next()
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
next()
|
||||
})
|
||||
|
||||
export default router
|
||||
|
@@ -20,7 +20,10 @@ export default {
|
||||
},
|
||||
async fetchData() {
|
||||
try {
|
||||
const response = await fetch(this.api_url + '/task/get')
|
||||
const response = await fetch(this.api_url + '/task/get', {
|
||||
credentials: 'include'
|
||||
})
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! Status: ${response.status}`)
|
||||
}
|
||||
@@ -36,6 +39,7 @@ export default {
|
||||
try {
|
||||
const response = await fetch(this.api_url + url, {
|
||||
method: 'POST',
|
||||
credentials: 'include',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
|
@@ -1,15 +1,33 @@
|
||||
<script setup>
|
||||
import router from '@/router'
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<form>
|
||||
<input type="email" placeholder="Email">
|
||||
<input type="password" placeholder="Password">
|
||||
<button>Log in</button>
|
||||
</form>
|
||||
<form>
|
||||
<label for="email">Email:</label>
|
||||
<input type="email" id="email" v-model="email" placeholder="Email" />
|
||||
<label for="password">Password:</label>
|
||||
<input type="password" id="password" v-model="password" placeholder="Password" />
|
||||
<button @click.prevent="formAction">Log in</button>
|
||||
</form>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
<script>
|
||||
import User from '@/api/user'
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
email: '',
|
||||
password: ''
|
||||
}
|
||||
</style>
|
||||
},
|
||||
methods: {
|
||||
async formAction() {
|
||||
const status = await User.loginUser({ email: this.email, password: this.password })
|
||||
if (status.code == 200) {
|
||||
throw router.push('/')
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
@@ -1,3 +1,36 @@
|
||||
<script setup>
|
||||
import router from '@/router'
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<b>signup</b>
|
||||
</template>
|
||||
<form>
|
||||
<label for="username">Username:</label>
|
||||
<input type="text" id="username" v-model="username" placeholder="Username" />
|
||||
<label for="email">Email:</label>
|
||||
<input type="email" id="email" v-model="email" placeholder="Email" />
|
||||
<label for="password">Password:</label>
|
||||
<input type="password" id="password" v-model="password" placeholder="Password" />
|
||||
<button @click.prevent="formAction">Sign up</button>
|
||||
</form>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import User from '@/api/user'
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
username: '',
|
||||
email: '',
|
||||
password: ''
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
async formAction() {
|
||||
const status = await User.registerUser({ username: this.username, email: this.email, password: this.password })
|
||||
if (status.code == 201) {
|
||||
throw router.push('/')
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
Reference in New Issue
Block a user