diff --git a/.DS_Store b/.DS_Store
index 9c48bff1..ec7f309c 100644
Binary files a/.DS_Store and b/.DS_Store differ
diff --git a/starter-project-web-react/components/NavBar.jsx b/starter-project-web-react/components/NavBar.jsx
index 4a87fd0e..7394b4ab 100644
--- a/starter-project-web-react/components/NavBar.jsx
+++ b/starter-project-web-react/components/NavBar.jsx
@@ -27,7 +27,7 @@ export default function ButtonAppBar() {
email: session.user.email,
})
}
- }, [])
+ }, [session, user])
const openProfile = () => {
router.push('/profile')
diff --git a/starter-project-web-react/components/mintesnot/Layout.jsx b/starter-project-web-react/components/mintesnot/Layout.jsx
new file mode 100644
index 00000000..5832c2f7
--- /dev/null
+++ b/starter-project-web-react/components/mintesnot/Layout.jsx
@@ -0,0 +1,13 @@
+import React from 'react'
+import NavBar from './NavBar'
+
+const Layout = ({children}) => {
+ return (
+
+
+ {children}
+
+ )
+}
+
+export default Layout
\ No newline at end of file
diff --git a/starter-project-web-react/components/mintesnot/NavBar.jsx b/starter-project-web-react/components/mintesnot/NavBar.jsx
new file mode 100644
index 00000000..de0e3f30
--- /dev/null
+++ b/starter-project-web-react/components/mintesnot/NavBar.jsx
@@ -0,0 +1,84 @@
+import AppBar from '@mui/material/AppBar'
+import Box from '@mui/material/Box'
+import Toolbar from '@mui/material/Toolbar'
+import Typography from '@mui/material/Typography'
+import Avatar from '@mui/material/Avatar'
+import LogoutIcon from '@mui/icons-material/Logout'
+import Button from '@mui/material/Button'
+import { useSession, signOut } from 'next-auth/react'
+import { useEffect, useState } from 'react'
+import { useRouter } from 'next/router'
+
+export default function ButtonAppBar() {
+ const pages = ['Products', 'Pricing', 'Blog']
+ const { data: session } = useSession()
+ const [user, setUser] = useState({ email: '', fullname: '', image: '' })
+ const router = useRouter()
+
+ const logoutHandler = () => {
+ signOut({ callbackUrl: `${window.location.origin}/auth/login` })
+ }
+
+ useEffect(() => {
+ if (session) {
+ setUser({
+ ...user,
+ fullname: session.user.name,
+ email: session.user.email,
+ })
+ }
+ }, [session, user])
+
+ const openProfile = () => {
+ router.push('/mintesnot/profile')
+ }
+ const backToHome = () => {
+ router.push('/')
+ }
+ return (
+
+
+
+
+ Blog App (React Demo)
+
+ {session ? (
+ <>
+
+ {pages.map((page) => (
+
+ {page}
+
+ ))}
+
+
+
+ {user.fullname}
+
+
+
+ >
+ ) : (
+ ''
+ )}
+
+
+
+ )
+}
diff --git a/starter-project-web-react/components/mintesnot/blog/Comments.jsx b/starter-project-web-react/components/mintesnot/blog/Comments.jsx
new file mode 100644
index 00000000..24aa5ec0
--- /dev/null
+++ b/starter-project-web-react/components/mintesnot/blog/Comments.jsx
@@ -0,0 +1,38 @@
+import * as React from 'react'
+import {
+ Box,
+ Card,
+ CardContent,
+ TextField,
+ List,
+ InputAdornment,
+} from '@mui/material/Box'
+import AddCommentOutlined from '@mui/icons-material/AddCommentOutlined'
+
+export default function Comments({ blog }) {
+ return (
+
+
+
+
+
+
+
+ )
+}
diff --git a/starter-project-web-react/components/mintesnot/blog/Details.jsx b/starter-project-web-react/components/mintesnot/blog/Details.jsx
new file mode 100644
index 00000000..80c81e71
--- /dev/null
+++ b/starter-project-web-react/components/mintesnot/blog/Details.jsx
@@ -0,0 +1,41 @@
+import React from 'react'
+import Moment from 'moment'
+import Typography from '@mui/material/Typography'
+import Image from 'next/image'
+
+const Details = ({ blog }) => {
+ const formattedDate = Moment(blog.createdAt).format('MMMM DD, YYYY')
+ return (
+
+
+ {blog.title}
+
+
+ Posted on `{formattedDate}` by{' '}
+ {blog.authorUserId.fullName}
+
+
+
+ {blog.content}
+
+
+ {blog.imageUrls ? (
+ blog.imageUrls.map((url, index) => (
+
+ ))
+ ) : (
+ <>>
+ )}
+
+ )
+}
+
+export default Details
diff --git a/starter-project-web-react/components/mintesnot/blog/SingleComment.jsx b/starter-project-web-react/components/mintesnot/blog/SingleComment.jsx
new file mode 100644
index 00000000..b1e6ff6b
--- /dev/null
+++ b/starter-project-web-react/components/mintesnot/blog/SingleComment.jsx
@@ -0,0 +1,42 @@
+import * as React from 'react';
+import Box from '@mui/material/Box';
+import Typography from '@mui/material/Typography';
+import ListItem from '@mui/material/ListItem';
+import Divider from '@mui/material/Divider';
+import ListItemText from '@mui/material/ListItemText';
+import ListItemAvatar from '@mui/material/ListItemAvatar';
+import Avatar from '@mui/material/Avatar';
+import Moment from 'moment';
+
+
+export default function SingleComment({comment, divider}) {
+ const formattedDate = Moment(comment.created_at).fromNow()
+ return (
+
+
+
+
+
+
+
+ {formattedDate}
+
+ {' — ' + comment.text}
+
+ }
+ />
+
+ {
+ divider &&
+ }
+
+ );
+}
diff --git a/starter-project-web-react/components/mintesnot/blog/blogCard.tsx b/starter-project-web-react/components/mintesnot/blog/blogCard.tsx
new file mode 100644
index 00000000..4305509f
--- /dev/null
+++ b/starter-project-web-react/components/mintesnot/blog/blogCard.tsx
@@ -0,0 +1,58 @@
+import * as React from 'react'
+import Card from '@mui/material/Card'
+import Box from '@mui/material/Box'
+import CardHeader from '@mui/material/CardHeader'
+import CardContent from '@mui/material/CardContent'
+import Avatar from '@mui/material/Avatar'
+import Typography from '@mui/material/Typography'
+import { red } from '@mui/material/colors'
+import Link from 'next/link'
+import CardActions from '@mui/material/CardActions'
+import Button from '@mui/material/Button'
+
+export default function BlogCard({ blog }: any) {
+ const { _id, title, content, authorUserId } = blog
+ const author = authorUserId.fullName
+ return (
+
+
+
+
+ {author.charAt(0).toUpperCase()}
+
+ }
+ title={author.charAt(0).toUpperCase() + author.slice(1)}
+ subheader="September 14, 2016"
+ />
+
+
+ {title}
+
+
+ {content}
+
+
+
+
+ Read More
+
+
+
+
+
+ )
+}
diff --git a/starter-project-web-react/components/mintesnot/blog/blogPostDialog.tsx b/starter-project-web-react/components/mintesnot/blog/blogPostDialog.tsx
new file mode 100644
index 00000000..949ab224
--- /dev/null
+++ b/starter-project-web-react/components/mintesnot/blog/blogPostDialog.tsx
@@ -0,0 +1,36 @@
+import React from 'react'
+import {
+ Box,
+ DialogActions,
+ Dialog,
+ DialogContent,
+ DialogTitle,
+ useMediaQuery,
+} from '@mui/material'
+import { useTheme } from '@mui/material/styles'
+import BlogPostForm from './blogPostForm'
+
+export default function BlogPostDialog({ open, handleClose }: any) {
+ const theme = useTheme()
+ const fullScreen = useMediaQuery(theme.breakpoints.down('md'))
+
+ return (
+
+
+
+ Blog Post
+
+
+
+
+
+
+
+ )
+}
diff --git a/starter-project-web-react/components/mintesnot/blog/blogPostForm.tsx b/starter-project-web-react/components/mintesnot/blog/blogPostForm.tsx
new file mode 100644
index 00000000..05a19bcc
--- /dev/null
+++ b/starter-project-web-react/components/mintesnot/blog/blogPostForm.tsx
@@ -0,0 +1,54 @@
+import React from 'react'
+import { Box, Button } from '@mui/material'
+import { Formik, Form } from 'formik'
+import * as Yup from 'yup'
+import BlogPostTextField from './blogPostTextField'
+
+type handle = () => void
+interface props {
+ handleClose: handle
+}
+export default function BlogPostForm({ handleClose }: props) {
+ const INITIAL_FORM_STATE = {
+ title: '',
+ content: '',
+ }
+ const FORM_VALIDATION = Yup.object().shape({
+ title: Yup.string().min(1).required(),
+ content: Yup.string().required(),
+ })
+ return (
+
+ {
+ handleClose()
+ }}
+ >
+
+
+
+ )
+}
diff --git a/starter-project-web-react/components/mintesnot/blog/blogPostTextField.tsx b/starter-project-web-react/components/mintesnot/blog/blogPostTextField.tsx
new file mode 100644
index 00000000..705e15ec
--- /dev/null
+++ b/starter-project-web-react/components/mintesnot/blog/blogPostTextField.tsx
@@ -0,0 +1,33 @@
+import React from 'react'
+import { TextField } from '@mui/material'
+import { useField } from 'formik'
+interface props {
+ name:string,
+ otherProps:any
+}
+export default function BlogPostTextField({
+ name,
+ otherProps
+}:props) {
+ const [field, mata]:any = useField(name);
+
+ const configTextfield = {
+ ...field,
+ ...otherProps,
+ fullWidth: true,
+ variant: 'outlined',
+ error:false,
+ helperText :"",
+ id:'fullwidth'
+ };
+ // (configTextfield)
+ if (mata && mata.touched && mata.error) {
+ configTextfield.error = true;
+ configTextfield.helperText = mata.error;
+ }
+ return (
+
+
+
+ )
+}
\ No newline at end of file
diff --git a/starter-project-web-react/components/mintesnot/blog/postBlogButton.tsx b/starter-project-web-react/components/mintesnot/blog/postBlogButton.tsx
new file mode 100644
index 00000000..d8e27ef9
--- /dev/null
+++ b/starter-project-web-react/components/mintesnot/blog/postBlogButton.tsx
@@ -0,0 +1,25 @@
+import React, { useState } from 'react'
+import { Button, Typography } from '@mui/material'
+import BlogPostDialog from './blogPostDialog'
+
+export default function PostBlog(props: any) {
+ const [open, setOpen] = useState(false)
+
+ const handleClickOpen = () => {
+ setOpen(true)
+ }
+
+ const handleClose = () => {
+ setOpen(false)
+ }
+ return (
+
+
+
+ Post Blog
+
+
+
+
+ )
+}
diff --git a/starter-project-web-react/components/mintesnot/profile/ProfileCard.tsx b/starter-project-web-react/components/mintesnot/profile/ProfileCard.tsx
new file mode 100644
index 00000000..eeb45a9e
--- /dev/null
+++ b/starter-project-web-react/components/mintesnot/profile/ProfileCard.tsx
@@ -0,0 +1,193 @@
+import * as React from 'react'
+import { Card, Box, Avatar, Switch, Grid, CardContent } from '@mui/material'
+import LocationOn from '@mui/icons-material/LocationOn'
+
+import {
+ Alert,
+ AlertTitle,
+ CardHeader,
+ CircularProgress,
+ TextField,
+ Button,
+} from '@mui/material'
+import { useState, useEffect } from 'react'
+import * as yup from 'yup'
+import { useSession } from 'next-auth/react'
+import { Form, Formik } from 'formik'
+import AuthApiCall from '../../../util/AuthApiCall'
+import IconButton from '@mui/material/IconButton'
+import CloseIcon from '@mui/icons-material/Close'
+import { useRouter } from 'next/router'
+
+const ProfileCard = () => {
+ const { data: session } = useSession()
+ const router = useRouter()
+
+ const INITIAL_STATE = {
+ firstname: session?.user?.name?.split(' ')[0] || '',
+ lastname: session?.user?.name?.split(' ')[1] || '',
+ email: session?.user?.email || '',
+ password: '',
+ confirmPassword: '',
+ }
+
+ const [INITIAL_STATE_VALUE, setInitialValue] = useState(INITIAL_STATE)
+ const [isUpdated, setIsUpdated] = useState(false)
+ const [updateFail, setUpdateFailed] = useState('')
+ const [loading, setLoading] = useState(false)
+
+ const FORM_VALIDATION = yup.object().shape({
+ firstname: yup.string().required('Required'),
+ lastname: yup.string().required('Required'),
+ email: yup.string().required('Required').email('Invalid Email'),
+ password: yup.string().min(8).required('Required'),
+ confirmPassword: yup.string().min(8).required('Required'),
+ })
+
+ return (
+
+
+
+
+
+
+
+
+
+ Scranton, PA
+
+ Lorem ipsum dolor sit amet consectetur, adipisicing elit.
+ Repudiandae aliquam voluptatibus sint accusamus sit cupiditate at
+ cumque doloribus nesciunt, deserunt, nam perspiciatis, sapiente
+ itaque? Totam rerum beatae hic facilis quia?
+
+
+ Online
+
+
+
+ {
+ setLoading(true)
+ if (value.password !== value.confirmPassword) {
+ setUpdateFailed("Password don't match")
+ } else {
+ const user = {
+ fullName: `${value.firstname} ${value.lastname}`,
+ email: value.email,
+ password: value.password,
+ }
+ const res = await AuthApiCall.UpdateUser(
+ user,
+ session?.id,
+ session?.access_token
+ )
+ if (res) {
+ setIsUpdated(true)
+ } else {
+ setUpdateFailed('User Update Failed!')
+ }
+ setLoading(false)
+ }
+ }}
+ >
+
+
+
+ {isUpdated ? (
+ {
+ setIsUpdated(false)
+ }}
+ >
+
+
+ }
+ sx={{ mb: 2 }}
+ >
+ Success
+ User Registered Successfully!
+
+ ) : updateFail ? (
+ {
+ setUpdateFailed('')
+ }}
+ >
+
+
+ }
+ sx={{ mb: 2 }}
+ >
+ Failed
+ User Failed to register!
+
+ ) : (
+ ''
+ )}
+
+ )
+}
+
+export default ProfileCard
diff --git a/starter-project-web-react/pages/blog/[id]/index.jsx b/starter-project-web-react/pages/blog/[id]/index.jsx
index f3cbfcbf..122464df 100644
--- a/starter-project-web-react/pages/blog/[id]/index.jsx
+++ b/starter-project-web-react/pages/blog/[id]/index.jsx
@@ -8,18 +8,16 @@ import { useSelector, useDispatch } from 'react-redux'
import { getSingleBlog, loadSingleBlog } from '../../../store/slices/blogs'
import { getSession } from 'next-auth/react'
-
const BlogDetail = () => {
const blog = useSelector((state) => getSingleBlog(state))
const dispatch = useDispatch()
-
+
const router = useRouter()
useEffect(() => {
-
dispatch(loadSingleBlog(router.query.id))
- }, [])
+ })
return (
diff --git a/starter-project-web-react/pages/blogs.tsx b/starter-project-web-react/pages/blogs.tsx
index 58121a8f..cc09f71a 100644
--- a/starter-project-web-react/pages/blogs.tsx
+++ b/starter-project-web-react/pages/blogs.tsx
@@ -21,21 +21,19 @@ const Blogs = () => {
const isLoading = useSelector((state: any) => isBlogLoading(state))
useEffect(() => {
dispatch(loadBlogs() as any)
- }, [])
+ })
const [pageNumber, setPageNumber] = useState(0)
const blogsPerPage = 5
const pagesVisited = pageNumber * blogsPerPage
const displayBlogs = blogs
- .slice(pagesVisited, pagesVisited+blogsPerPage)
+ .slice(pagesVisited, pagesVisited + blogsPerPage)
.map((blog: any) => {
- return (
-
- )
+ return
})
- const pageCount = Math.ceil(blogs.length/blogsPerPage)
+ const pageCount = Math.ceil(blogs.length / blogsPerPage)
const changePage = (event: { selected: react.SetStateAction }) => {
setPageNumber(event.selected)
@@ -85,11 +83,11 @@ const Blogs = () => {
nextLabel="Next"
pageCount={pageCount}
onPageChange={changePage}
- containerClassName={"paginationBttns"}
- previousLinkClassName={"previousBttn"}
- nextLinkClassName={"nextBttn"}
- disabledClassName={"paginationDisabled"}
- activeClassName={"paginationActive"}
+ containerClassName={'paginationBttns'}
+ previousLinkClassName={'previousBttn'}
+ nextLinkClassName={'nextBttn'}
+ disabledClassName={'paginationDisabled'}
+ activeClassName={'paginationActive'}
/>
)}
diff --git a/starter-project-web-react/pages/mintesnot/blog/[id]/index.tsx b/starter-project-web-react/pages/mintesnot/blog/[id]/index.tsx
new file mode 100644
index 00000000..061f7dff
--- /dev/null
+++ b/starter-project-web-react/pages/mintesnot/blog/[id]/index.tsx
@@ -0,0 +1,34 @@
+import { useRouter } from 'next/router'
+import { CircularProgress, Container, Box, Grid } from '@mui/material'
+
+import Details from '../../../../components/mintesnot/blog/Details'
+import { useFetchSinglBlogQuery } from '../../../../store/mintesnot/blog/BlogApiSlice'
+const BlogDetail = () => {
+ const router = useRouter()
+ const { data = {}, isFetching } = useFetchSinglBlogQuery(
+ router.query.id as string
+ )
+
+ return (
+
+
+
+ {!isFetching ? (
+
+ ) : (
+
+
+
+ )}
+
+
+
+ )
+}
+
+export default BlogDetail
diff --git a/starter-project-web-react/pages/mintesnot/index.tsx b/starter-project-web-react/pages/mintesnot/index.tsx
new file mode 100644
index 00000000..86ad5caa
--- /dev/null
+++ b/starter-project-web-react/pages/mintesnot/index.tsx
@@ -0,0 +1,59 @@
+import react from 'react'
+import { Box, Container, Grid, Typography, Divider } from '@mui/material'
+import CircularProgress from '@mui/material/CircularProgress'
+import { useFetchBlogsQuery } from '../../store/mintesnot/blog/BlogApiSlice'
+import PostBlog from '../../components/mintesnot/blog/postBlogButton'
+import BlogCard from '../../components/mintesnot/blog/blogCard'
+
+const Blogs = () => {
+ const { data = [], isFetching } = useFetchBlogsQuery()
+
+ return (
+
+
+
+
+ Blogs
+
+
+
+
+
+
+
+
+
+
+
+
+ {isFetching ? (
+
+
+
+ ) : (
+
+ {data.map((blog: any) => {
+ return
+ })}
+
+ )}
+
+ )
+}
+
+export default Blogs
diff --git a/starter-project-web-react/pages/mintesnot/profile.tsx b/starter-project-web-react/pages/mintesnot/profile.tsx
new file mode 100644
index 00000000..c8fb7f99
--- /dev/null
+++ b/starter-project-web-react/pages/mintesnot/profile.tsx
@@ -0,0 +1,4 @@
+const ProfilePage = () => {
+ return <>>
+}
+export default ProfilePage
diff --git a/starter-project-web-react/store/hooks.ts b/starter-project-web-react/store/hooks.ts
new file mode 100644
index 00000000..d2843e8a
--- /dev/null
+++ b/starter-project-web-react/store/hooks.ts
@@ -0,0 +1,6 @@
+import { TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux'
+import type { RootState, AppDispatch } from './configureStore'
+
+// Use throughout your app instead of plain `useDispatch` and `useSelector`
+export const useAppDispatch: () => AppDispatch = useDispatch
+export const useAppSelector: TypedUseSelectorHook = useSelector
\ No newline at end of file
diff --git a/starter-project-web-react/store/mintesnot/app.ts b/starter-project-web-react/store/mintesnot/app.ts
new file mode 100644
index 00000000..9886924d
--- /dev/null
+++ b/starter-project-web-react/store/mintesnot/app.ts
@@ -0,0 +1,21 @@
+import { configureStore, } from "@reduxjs/toolkit";
+import blogReducer from "./blog/Blog"
+import { blogApiSlice } from "./blog/BlogApiSlice";
+
+
+export const store = configureStore({
+ reducer:{
+ blog: blogReducer,
+ [blogApiSlice.reducerPath]: blogApiSlice.reducer
+ },
+ middleware: (getDefaultMiddleware)=>{
+ return getDefaultMiddleware().concat(blogApiSlice.middleware)
+ }
+
+})
+
+export type RootState = ReturnType
+export type AppDispatch = typeof store.dispatch
+
+
+
diff --git a/starter-project-web-react/store/mintesnot/blog/Blog.ts b/starter-project-web-react/store/mintesnot/blog/Blog.ts
new file mode 100644
index 00000000..53021799
--- /dev/null
+++ b/starter-project-web-react/store/mintesnot/blog/Blog.ts
@@ -0,0 +1,48 @@
+import { createSlice, PayloadAction } from "@reduxjs/toolkit";
+import type {RootState} from "../app"
+
+interface BlogState {
+ value: object[],
+ loading: boolean,
+ commentLoading:boolean,
+ error:string | null,
+ singleBlog: object,
+ comments: object[]
+}
+
+const initialState = {
+ value: [],
+ loading: false,
+ commentLoading: false,
+ error: null,
+ singleBlog: {},
+ comments:[]
+} as BlogState
+
+export const blogSlice = createSlice({
+ name: 'blog',
+ initialState,
+ reducers:{
+ postAdded: (state, action:PayloadAction) => {
+ state.value = [...state.value, action.payload]
+ state.loading = false
+ state.error = null
+ },
+ singleLoaded: (state, action:PayloadAction) => {
+ state.singleBlog = action.payload
+ state.loading = false
+ state.error = null
+ },
+ commentsLoaded: (state, action:PayloadAction) => {
+ state.comments = action.payload
+ state.commentLoading = false
+ },
+ commentAdded: (state) => {
+ state.commentLoading = false
+ }
+ }
+})
+
+export const { postAdded, commentAdded , singleLoaded, commentsLoaded } = blogSlice.actions
+
+export default blogSlice.reducer
\ No newline at end of file
diff --git a/starter-project-web-react/store/mintesnot/blog/BlogApiSlice.ts b/starter-project-web-react/store/mintesnot/blog/BlogApiSlice.ts
new file mode 100644
index 00000000..77b16332
--- /dev/null
+++ b/starter-project-web-react/store/mintesnot/blog/BlogApiSlice.ts
@@ -0,0 +1,44 @@
+import {createApi, fetchBaseQuery} from '@reduxjs/toolkit/query/react'
+
+
+interface Blog
+ {
+ _id: "",
+ authorUserId: {
+ fullName: "",
+ email: "",
+ __v: 0
+ },
+ title: "",
+ content: "",
+ imageUrls: [],
+ rating: {},
+ description: "",
+ createdAt: "",
+ updatedAt: "",
+ __v: 0
+
+}
+
+export const blogApiSlice = createApi({
+ reducerPath: 'api',
+ baseQuery: fetchBaseQuery({
+ baseUrl:'https://blog-app-backend.onrender.com/api'
+ }),
+ endpoints(builder){
+ return {
+ fetchBlogs: builder.query({
+ query(limit = 10){
+ return `/articles/all`
+ }
+ }),
+ fetchSinglBlog: builder.query({
+ query(id) {
+ return `/articles/${id}`
+ },
+ })
+ }
+ }
+})
+
+export const {useFetchBlogsQuery, useFetchSinglBlogQuery} = blogApiSlice
\ No newline at end of file
diff --git a/starter-project-web-vue2/components/andualem/AndualemAddBlog.vue b/starter-project-web-vue2/components/andualem/AndualemAddBlog.vue
new file mode 100644
index 00000000..e69de29b
diff --git a/starter-project-web-vue2/components/andualem/AndualemBlogPost.vue b/starter-project-web-vue2/components/andualem/AndualemBlogPost.vue
new file mode 100644
index 00000000..e69de29b
diff --git a/starter-project-web-vue2/components/andualem/NavigationBar.vue b/starter-project-web-vue2/components/andualem/NavigationBar.vue
new file mode 100644
index 00000000..e69de29b
diff --git a/starter-project-web-vue2/components/andualem/UserAuthForm.vue b/starter-project-web-vue2/components/andualem/UserAuthForm.vue
new file mode 100644
index 00000000..e69de29b
diff --git a/starter-project-web-vue2/components/keiredin/KeiredinBlogPost.vue b/starter-project-web-vue2/components/keiredin/KeiredinBlogPost.vue
index 78eb7563..77048be5 100644
--- a/starter-project-web-vue2/components/keiredin/KeiredinBlogPost.vue
+++ b/starter-project-web-vue2/components/keiredin/KeiredinBlogPost.vue
@@ -1,39 +1,25 @@
-
+
-
-
-
-
+
+
+
+
-
-
- mdi-twitter
-
+ style="text-decoration: none; color: inherit"
+ :to="'/keiredin/id'"
+ >
+ mdi-twitter
Title
- "Turns out semicolon-less style is easier and safer in TS because most gotcha edge cases are type invalid as well."
+ "Turns out semicolon-less style is easier and safer in TS because
+ most gotcha edge cases are type invalid as well."
@@ -50,30 +36,22 @@
Evan You
-
+
-
- mdi-pencil
-
- edit
+ mdi-pencil
+ edit
-
- mdi-delete
-
+ mdi-delete
delete
-
-
-
+
+
@@ -82,8 +60,7 @@ import AddBlog from '../keiredin/KeiredinNewBlog.vue'
export default {
name: 'BlogPost',
components: {
- AddBlog
- }
-
+ AddBlog,
+ },
}
diff --git a/starter-project-web-vue2/components/keiredin/KeiredinNewBlog.vue b/starter-project-web-vue2/components/keiredin/KeiredinNewBlog.vue
index 16eabd54..d0ea8ef9 100644
--- a/starter-project-web-vue2/components/keiredin/KeiredinNewBlog.vue
+++ b/starter-project-web-vue2/components/keiredin/KeiredinNewBlog.vue
@@ -1,11 +1,7 @@
-
+
mdi-plus
Add New Blog
@@ -26,13 +22,8 @@
-
-
-
-
-
diff --git a/starter-project-web-vue2/components/liben/LibenArticle.vue b/starter-project-web-vue2/components/liben/LibenArticle.vue
new file mode 100644
index 00000000..779e0573
--- /dev/null
+++ b/starter-project-web-vue2/components/liben/LibenArticle.vue
@@ -0,0 +1,74 @@
+
+
+ {{ article.title }}
+
+
+
+
+
+
+ by {{ article.authorUserId.fullName }}
+
+
+
+
+ {{ formatTime(article.updatedAt) }}
+
+
+
+ {{ article.description }}
+
+
+
+
+
+ Tags
+
+
+
+ {{
+ cat
+ }}
+
+ No tags
+
+
+
+
diff --git a/starter-project-web-vue2/components/liben/LibenArticleComment.vue b/starter-project-web-vue2/components/liben/LibenArticleComment.vue
new file mode 100644
index 00000000..a6a63281
--- /dev/null
+++ b/starter-project-web-vue2/components/liben/LibenArticleComment.vue
@@ -0,0 +1,35 @@
+
+
+
+
+
+
+
+
+
+
+ {{ comment.user.fullName }}
+ {{ comment.text }}
+ {{
+ formatTime(comment.updatedAt)
+ }}
+
+
+
+
+
diff --git a/starter-project-web-vue2/components/liben/LibenArticleDetail.vue b/starter-project-web-vue2/components/liben/LibenArticleDetail.vue
new file mode 100644
index 00000000..a2d9fe09
--- /dev/null
+++ b/starter-project-web-vue2/components/liben/LibenArticleDetail.vue
@@ -0,0 +1,70 @@
+
+
+
+
+
+
+ mdi-pencil
+
+
+
+
+ mdi-delete
+
+
+
+
+
+
+
+
{{ article.title }}
+
+
+ {{ formatTime(article.updatedAt) }}
+
+ by {{ article.authorUserId.fullName }}
+
+
+
{{ article.description }}
+
+
+
+
+
+
{{ article.content }}
+
+
+
diff --git a/starter-project-web-vue2/components/liben/LibenArticleForm.vue b/starter-project-web-vue2/components/liben/LibenArticleForm.vue
new file mode 100644
index 00000000..8c38dd85
--- /dev/null
+++ b/starter-project-web-vue2/components/liben/LibenArticleForm.vue
@@ -0,0 +1,72 @@
+
+
+
+
diff --git a/starter-project-web-vue2/components/liben/LibenArticleSearch.vue b/starter-project-web-vue2/components/liben/LibenArticleSearch.vue
new file mode 100644
index 00000000..807b2e6c
--- /dev/null
+++ b/starter-project-web-vue2/components/liben/LibenArticleSearch.vue
@@ -0,0 +1,49 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/starter-project-web-vue2/components/liben/LibenCommentForm.vue b/starter-project-web-vue2/components/liben/LibenCommentForm.vue
new file mode 100644
index 00000000..a1602f4d
--- /dev/null
+++ b/starter-project-web-vue2/components/liben/LibenCommentForm.vue
@@ -0,0 +1,53 @@
+
+
+
+
+
+
+
+
+
+
+
+ mdi-arrow-up-bold-box-outline
+
+
+
+
diff --git a/starter-project-web-vue2/components/liben/LibenDialog.vue b/starter-project-web-vue2/components/liben/LibenDialog.vue
new file mode 100644
index 00000000..9a935877
--- /dev/null
+++ b/starter-project-web-vue2/components/liben/LibenDialog.vue
@@ -0,0 +1,68 @@
+
+
+
+
+
+ Are you sure you want to delete {{ title }}?
+
+
+ Remember this action is irreversible.
+
+
+
+
+
+ Cancel
+
+
+
+ Delete
+
+
+
+
+
+
+
diff --git a/starter-project-web-vue2/components/liben/LoadingBar.vue b/starter-project-web-vue2/components/liben/LoadingBar.vue
new file mode 100644
index 00000000..bb7730bf
--- /dev/null
+++ b/starter-project-web-vue2/components/liben/LoadingBar.vue
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+
diff --git a/starter-project-web-vue2/components/natnaelT/AddBlogButton.vue b/starter-project-web-vue2/components/natnaelT/AddBlogButton.vue
new file mode 100644
index 00000000..ab5503d3
--- /dev/null
+++ b/starter-project-web-vue2/components/natnaelT/AddBlogButton.vue
@@ -0,0 +1,17 @@
+
+ {{ text }}
+
+
diff --git a/starter-project-web-vue2/components/natnaelT/AddBlogForm.vue b/starter-project-web-vue2/components/natnaelT/AddBlogForm.vue
new file mode 100644
index 00000000..9ca2ef62
--- /dev/null
+++ b/starter-project-web-vue2/components/natnaelT/AddBlogForm.vue
@@ -0,0 +1,102 @@
+
+
+
+
+
+
+
+
+
+
+
+ Save Blog
+
+
+
+
+
+
diff --git a/starter-project-web-vue2/components/natnaelT/BlogList.vue b/starter-project-web-vue2/components/natnaelT/BlogList.vue
new file mode 100644
index 00000000..a69ca503
--- /dev/null
+++ b/starter-project-web-vue2/components/natnaelT/BlogList.vue
@@ -0,0 +1,47 @@
+
+
+
+
+
+
diff --git a/starter-project-web-vue2/components/natnaelT/SingleBlog.vue b/starter-project-web-vue2/components/natnaelT/SingleBlog.vue
new file mode 100644
index 00000000..0976a21d
--- /dev/null
+++ b/starter-project-web-vue2/components/natnaelT/SingleBlog.vue
@@ -0,0 +1,23 @@
+
+
+
+ {{ blog.title }}
+ {{ blog.content }}
+ Update
+ Delete
+
+ Show more
+
+
+
+
+
+
diff --git a/starter-project-web-vue2/components/yared/AddBlog.vue b/starter-project-web-vue2/components/yared/AddBlog.vue
new file mode 100644
index 00000000..4a47e1ab
--- /dev/null
+++ b/starter-project-web-vue2/components/yared/AddBlog.vue
@@ -0,0 +1,76 @@
+
+
+
+
+
+ mdi-plus-thick
+
+
+
+
+ Add a New Blog
+
+
+
+
+
+
+
+
+
+ Add Blog
+
+
+
+
+
+
+
+
diff --git a/starter-project-web-vue2/components/yared/Blog.vue b/starter-project-web-vue2/components/yared/Blog.vue
new file mode 100644
index 00000000..13b4d87b
--- /dev/null
+++ b/starter-project-web-vue2/components/yared/Blog.vue
@@ -0,0 +1,67 @@
+
+
+
+
+
+ {{ blog.title }}
+
+
+
+ ID: {{ blog._id }}
+
+
+
+ mdi-minus
+
+
+
+
+
+
+
diff --git a/starter-project-web-vue2/components/yared/Blogs.vue b/starter-project-web-vue2/components/yared/Blogs.vue
new file mode 100644
index 00000000..b75073cd
--- /dev/null
+++ b/starter-project-web-vue2/components/yared/Blogs.vue
@@ -0,0 +1,44 @@
+
+
+
+
List of Blogs
+
+
+ Log Out
+
+
+ Log In
+ Sign Up
+
+
+
+
+
+
+
+
+
+
diff --git a/starter-project-web-vue2/components/yared/UpdateBlog.vue b/starter-project-web-vue2/components/yared/UpdateBlog.vue
new file mode 100644
index 00000000..ce308dc9
--- /dev/null
+++ b/starter-project-web-vue2/components/yared/UpdateBlog.vue
@@ -0,0 +1,56 @@
+
+
+
+ Update
+
+
+
+ Update Blog
+
+
+
+
+
+
+
+
+
+ Update Blog
+
+
+
+
+
+
+
diff --git a/starter-project-web-vue2/components/yohans/AddBlog.vue b/starter-project-web-vue2/components/yohans/AddBlog.vue
new file mode 100644
index 00000000..c8de278c
--- /dev/null
+++ b/starter-project-web-vue2/components/yohans/AddBlog.vue
@@ -0,0 +1,21 @@
+
+
+
+
+ mdi-plus
+ add blog
+
+
+
+ add blog
+
+
+
+
+ add blog
+
+
+
+
+
+
diff --git a/starter-project-web-vue2/components/yohans/BlogItem.vue b/starter-project-web-vue2/components/yohans/BlogItem.vue
new file mode 100644
index 00000000..01a3a3d5
--- /dev/null
+++ b/starter-project-web-vue2/components/yohans/BlogItem.vue
@@ -0,0 +1,33 @@
+
+
+
+
+ {{
+ blog.title
+ }}
+ {{ blog.content }}
+
+
+
+
+ mdi-pencil
+
+
+
+
+
+ mdi-delete
+
+
+
+
+
+
+
diff --git a/starter-project-web-vue2/components/yohans/BlogList.vue b/starter-project-web-vue2/components/yohans/BlogList.vue
new file mode 100644
index 00000000..b598f61f
--- /dev/null
+++ b/starter-project-web-vue2/components/yohans/BlogList.vue
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
diff --git a/starter-project-web-vue2/layouts/error.vue b/starter-project-web-vue2/layouts/error.vue
index 6834bd8e..c686e775 100644
--- a/starter-project-web-vue2/layouts/error.vue
+++ b/starter-project-web-vue2/layouts/error.vue
@@ -1,43 +1,45 @@
-
-
- {{ pageNotFound }}
-
-
- {{ otherError }}
-
- Home page
-
+
+
+
+
+
+ {{ message }}
+
+
+ Return to homepage
+
+
-
-
-
diff --git a/starter-project-web-vue2/middleware/unauthorized.js b/starter-project-web-vue2/middleware/unauthorized.js
new file mode 100644
index 00000000..e7b9e611
--- /dev/null
+++ b/starter-project-web-vue2/middleware/unauthorized.js
@@ -0,0 +1,7 @@
+export default function ({ $axios, redirect }) {
+ $axios.onError((error) => {
+ if (error.response.status === 401 || error.response.status === 403) {
+ redirect('/abraham/login')
+ }
+ })
+}
diff --git a/starter-project-web-vue2/nuxt.config.js b/starter-project-web-vue2/nuxt.config.js
index edc51496..c0c5e996 100644
--- a/starter-project-web-vue2/nuxt.config.js
+++ b/starter-project-web-vue2/nuxt.config.js
@@ -1,5 +1,4 @@
import colors from 'vuetify/es5/util/colors'
-
export default {
// Global page headers: https://go.nuxtjs.dev/config-head
head: {
@@ -20,6 +19,8 @@ export default {
// Global CSS: https://go.nuxtjs.dev/config-css
css: [],
+ loading: '@/components/liben/LoadingBar.vue',
+
// Plugins to run before rendering page: https://go.nuxtjs.dev/config-plugins
plugins: [],
@@ -39,6 +40,10 @@ export default {
// Modules: https://go.nuxtjs.dev/config-modules
modules: ['@nuxtjs/axios', '@nuxtjs/auth-next'],
+ axios: {
+ baseURL: 'https://blog-app-backend.onrender.com/api/',
+ },
+
// Vuetify module configuration: https://go.nuxtjs.dev/config-vuetify
vuetify: {
customVariables: ['~/assets/variables.scss'],
@@ -61,6 +66,10 @@ export default {
// Build Configuration: https://go.nuxtjs.dev/config-build
build: {},
+ router: {
+ middleware: 'unauthorized',
+ },
+
auth: {
strategies: {
local: {
diff --git a/starter-project-web-vue2/package-lock.json b/starter-project-web-vue2/package-lock.json
index a2edce30..f8431058 100644
--- a/starter-project-web-vue2/package-lock.json
+++ b/starter-project-web-vue2/package-lock.json
@@ -12,11 +12,12 @@
"@nuxtjs/auth-next": "5.0.0-1624817847.21691f1",
"@nuxtjs/axios": "^5.13.6",
"core-js": "^3.19.3",
+ "moment": "^2.29.4",
"nuxt": "^2.15.8",
"vue-server-renderer": "^2.6.14",
"vue-template-compiler": "^2.6.14",
"vuetify": "^2.6.1",
- "webpack": "^4.46.0"
+ "webpack": "^4.45.0"
},
"devDependencies": {
"@babel/eslint-parser": "^7.16.3",
@@ -5974,7 +5975,7 @@
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz",
"integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==",
- "devOptional": true,
+ "dev": true,
"dependencies": {
"file-uri-to-path": "1.0.0"
}
@@ -9721,7 +9722,7 @@
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz",
"integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==",
- "devOptional": true
+ "dev": true
},
"node_modules/fill-range": {
"version": "7.0.1",
@@ -10016,19 +10017,6 @@
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
"integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="
},
- "node_modules/fsevents": {
- "version": "2.3.2",
- "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
- "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
- "hasInstallScript": true,
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
- }
- },
"node_modules/function-bind": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
@@ -14527,6 +14515,14 @@
"mkdirp": "bin/cmd.js"
}
},
+ "node_modules/moment": {
+ "version": "2.29.4",
+ "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz",
+ "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==",
+ "engines": {
+ "node": "*"
+ }
+ },
"node_modules/move-concurrently": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz",
@@ -14586,12 +14582,6 @@
"resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz",
"integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA=="
},
- "node_modules/nan": {
- "version": "2.16.0",
- "resolved": "https://registry.npmjs.org/nan/-/nan-2.16.0.tgz",
- "integrity": "sha512-UdAqHyFngu7TfQKsCBgAA6pWDkT8MAO7d0jyOecVhN5354xbLqdn8mV9Tat9gepAupm0bt2DbeaSC8vS52MuFA==",
- "optional": true
- },
"node_modules/nanoid": {
"version": "2.1.11",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-2.1.11.tgz",
@@ -21074,24 +21064,6 @@
"node": ">=0.10.0"
}
},
- "node_modules/watchpack-chokidar2/node_modules/fsevents": {
- "version": "1.2.13",
- "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz",
- "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==",
- "deprecated": "fsevents 1 will break on node v14+ and could be using insecure binaries. Upgrade to fsevents 2.",
- "hasInstallScript": true,
- "optional": true,
- "os": [
- "darwin"
- ],
- "dependencies": {
- "bindings": "^1.5.0",
- "nan": "^2.12.1"
- },
- "engines": {
- "node": ">= 4.0"
- }
- },
"node_modules/watchpack-chokidar2/node_modules/glob-parent": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz",
@@ -26896,7 +26868,7 @@
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz",
"integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==",
- "devOptional": true,
+ "dev": true,
"requires": {
"file-uri-to-path": "1.0.0"
}
@@ -29776,7 +29748,7 @@
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz",
"integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==",
- "devOptional": true
+ "dev": true
},
"fill-range": {
"version": "7.0.1",
@@ -30000,12 +29972,6 @@
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
"integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="
},
- "fsevents": {
- "version": "2.3.2",
- "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
- "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
- "optional": true
- },
"function-bind": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
@@ -33347,6 +33313,11 @@
"minimist": "^1.2.6"
}
},
+ "moment": {
+ "version": "2.29.4",
+ "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz",
+ "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w=="
+ },
"move-concurrently": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz",
@@ -33396,12 +33367,6 @@
"resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz",
"integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA=="
},
- "nan": {
- "version": "2.16.0",
- "resolved": "https://registry.npmjs.org/nan/-/nan-2.16.0.tgz",
- "integrity": "sha512-UdAqHyFngu7TfQKsCBgAA6pWDkT8MAO7d0jyOecVhN5354xbLqdn8mV9Tat9gepAupm0bt2DbeaSC8vS52MuFA==",
- "optional": true
- },
"nanoid": {
"version": "2.1.11",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-2.1.11.tgz",
@@ -38458,16 +38423,6 @@
"to-regex-range": "^2.1.0"
}
},
- "fsevents": {
- "version": "1.2.13",
- "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz",
- "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==",
- "optional": true,
- "requires": {
- "bindings": "^1.5.0",
- "nan": "^2.12.1"
- }
- },
"glob-parent": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz",
diff --git a/starter-project-web-vue2/package.json b/starter-project-web-vue2/package.json
index 918272f2..0ed01f98 100644
--- a/starter-project-web-vue2/package.json
+++ b/starter-project-web-vue2/package.json
@@ -20,11 +20,12 @@
"@nuxtjs/auth-next": "5.0.0-1624817847.21691f1",
"@nuxtjs/axios": "^5.13.6",
"core-js": "^3.19.3",
+ "moment": "^2.29.4",
"nuxt": "^2.15.8",
"vue-server-renderer": "^2.6.14",
"vue-template-compiler": "^2.6.14",
"vuetify": "^2.6.1",
- "webpack": "^4.46.0"
+ "webpack": "^4.45.0"
},
"devDependencies": {
"@babel/eslint-parser": "^7.16.3",
diff --git a/starter-project-web-vue2/pages/andualem/index.vue b/starter-project-web-vue2/pages/andualem/index.vue
new file mode 100644
index 00000000..d2ccb6b6
--- /dev/null
+++ b/starter-project-web-vue2/pages/andualem/index.vue
@@ -0,0 +1,65 @@
+
+
+
+
+ Add Blog
+
+
+
+ Add a New Blog
+
+
+
+
+
+ Add Blog
+
+
+
+
+
+
+
+
+
+
+
+ {{ item.title }}
+
+
+ {{ item.content }}
+
+
+
+ mdi-pencil
+
+
+ mdi-delete
+
+
+
+
+
+
+
+
+
diff --git a/starter-project-web-vue2/pages/index.vue b/starter-project-web-vue2/pages/index.vue
index d47056b9..978ec13e 100644
--- a/starter-project-web-vue2/pages/index.vue
+++ b/starter-project-web-vue2/pages/index.vue
@@ -38,9 +38,9 @@ export default {
link: '/abraham',
},
{
- name: 'Aymen Mohammednur',
- description: 'Group 31 Member',
- link: '/aymen',
+ name: 'yohans',
+ description: 'Summer Intern',
+ link: '/yohans',
},
{
name: 'Amsale Gebrehana',
@@ -53,10 +53,30 @@ export default {
link: '/ruth',
},
{
- name: "Keiredin Aman",
+ name: 'Keiredin Aman',
description: 'Summer Intern',
link: '/keiredin',
},
+ {
+ name: 'Andualem Sebsbe',
+ description: 'Summer Intern',
+ link: '/andualem',
+ },
+ {
+ name: 'Liben',
+ description: 'Web Team Member',
+ link: '/liben/articles',
+ },
+ {
+ name: 'Yared Tegegn',
+ description: 'Group 32 Student',
+ link: '/yared',
+ },
+ {
+ name: 'Natnael Tedros',
+ description: 'G32 Web Team Member',
+ link: '/natnaelT',
+ },
],
}
},
diff --git a/starter-project-web-vue2/pages/keiredin/_id.vue b/starter-project-web-vue2/pages/keiredin/_id.vue
index 9524a081..8207f2bf 100644
--- a/starter-project-web-vue2/pages/keiredin/_id.vue
+++ b/starter-project-web-vue2/pages/keiredin/_id.vue
@@ -2,22 +2,17 @@
-
- mdi-arrow-left-bold-circle
-
+ mdi-arrow-left-bold-circle
Back To Blogs
-
Title:
+ Title:
- Content:
+ Content:
-
diff --git a/starter-project-web-vue2/pages/keiredin/index.vue b/starter-project-web-vue2/pages/keiredin/index.vue
index 02d842ef..2819c04d 100644
--- a/starter-project-web-vue2/pages/keiredin/index.vue
+++ b/starter-project-web-vue2/pages/keiredin/index.vue
@@ -13,4 +13,3 @@ export default {
components: { BlogPost },
}
-
diff --git a/starter-project-web-vue2/pages/liben/articles/_id/edit.vue b/starter-project-web-vue2/pages/liben/articles/_id/edit.vue
new file mode 100644
index 00000000..f011ce93
--- /dev/null
+++ b/starter-project-web-vue2/pages/liben/articles/_id/edit.vue
@@ -0,0 +1,42 @@
+
+
+
+
+ Edit Article
+
+
+
+
+
+
diff --git a/starter-project-web-vue2/pages/liben/articles/_id/index.vue b/starter-project-web-vue2/pages/liben/articles/_id/index.vue
new file mode 100644
index 00000000..31fc3e25
--- /dev/null
+++ b/starter-project-web-vue2/pages/liben/articles/_id/index.vue
@@ -0,0 +1,52 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Comments
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/starter-project-web-vue2/pages/liben/articles/create.vue b/starter-project-web-vue2/pages/liben/articles/create.vue
new file mode 100644
index 00000000..068e74b4
--- /dev/null
+++ b/starter-project-web-vue2/pages/liben/articles/create.vue
@@ -0,0 +1,34 @@
+
+
+
+
+ Create Article
+
+
+
+
+
+
diff --git a/starter-project-web-vue2/pages/liben/articles/index.vue b/starter-project-web-vue2/pages/liben/articles/index.vue
new file mode 100644
index 00000000..55fa1f6a
--- /dev/null
+++ b/starter-project-web-vue2/pages/liben/articles/index.vue
@@ -0,0 +1,34 @@
+
+
+ Create Article
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/starter-project-web-vue2/pages/natnaelT/_id.vue b/starter-project-web-vue2/pages/natnaelT/_id.vue
new file mode 100644
index 00000000..39884a1c
--- /dev/null
+++ b/starter-project-web-vue2/pages/natnaelT/_id.vue
@@ -0,0 +1,41 @@
+
+
+
+
+ mdi-arrow-left Back
+
+
+
+
+ {{ blog.title }}
+ {{ blog.content }}
+
+
+
+
+
+
diff --git a/starter-project-web-vue2/pages/natnaelT/index.vue b/starter-project-web-vue2/pages/natnaelT/index.vue
new file mode 100644
index 00000000..a41d4f03
--- /dev/null
+++ b/starter-project-web-vue2/pages/natnaelT/index.vue
@@ -0,0 +1,75 @@
+
+
+
+
+
+
+
diff --git a/starter-project-web-vue2/pages/sileshi/README.md b/starter-project-web-vue2/pages/sileshi/README.md
new file mode 100644
index 00000000..e69de29b
diff --git a/starter-project-web-vue2/pages/yared/_id.vue b/starter-project-web-vue2/pages/yared/_id.vue
new file mode 100644
index 00000000..4bafe682
--- /dev/null
+++ b/starter-project-web-vue2/pages/yared/_id.vue
@@ -0,0 +1,32 @@
+
+
+
{{ blog.title }}
+
+
+
Created at: {{ blog.createdAt }}
+
+
Go Back
+
+
+
+
diff --git a/starter-project-web-vue2/pages/yared/index.vue b/starter-project-web-vue2/pages/yared/index.vue
new file mode 100644
index 00000000..9ad9b4a3
--- /dev/null
+++ b/starter-project-web-vue2/pages/yared/index.vue
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
diff --git a/starter-project-web-vue2/pages/yared/login.vue b/starter-project-web-vue2/pages/yared/login.vue
new file mode 100644
index 00000000..cea78426
--- /dev/null
+++ b/starter-project-web-vue2/pages/yared/login.vue
@@ -0,0 +1,53 @@
+
+
+ Login
+
+
+
+
+
+
+ Login
+
+
+
+
+
diff --git a/starter-project-web-vue2/pages/yared/register.vue b/starter-project-web-vue2/pages/yared/register.vue
new file mode 100644
index 00000000..544fc047
--- /dev/null
+++ b/starter-project-web-vue2/pages/yared/register.vue
@@ -0,0 +1,61 @@
+
+
+ Register
+
+
+
+
+
+
+
+ Sign up
+
+
+
+
+
diff --git a/starter-project-web-vue2/pages/yohans/_blogDetail.vue b/starter-project-web-vue2/pages/yohans/_blogDetail.vue
new file mode 100644
index 00000000..aa4332ec
--- /dev/null
+++ b/starter-project-web-vue2/pages/yohans/_blogDetail.vue
@@ -0,0 +1,19 @@
+
+
+ {{ blog.title }}
+
+ {{ blog.content }}
+
+
+
diff --git a/starter-project-web-vue2/pages/yohans/index.vue b/starter-project-web-vue2/pages/yohans/index.vue
new file mode 100644
index 00000000..c012002d
--- /dev/null
+++ b/starter-project-web-vue2/pages/yohans/index.vue
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
diff --git a/starter-project-web-vue2/store/liben.js b/starter-project-web-vue2/store/liben.js
new file mode 100644
index 00000000..334c3a06
--- /dev/null
+++ b/starter-project-web-vue2/store/liben.js
@@ -0,0 +1,77 @@
+export const state = () => ({
+ articles: [],
+ article: {},
+ comments: [],
+})
+
+export const getters = {
+ articles: (state) => state.articles,
+ article: (state) => state.article,
+ comments: (state) => state.comments,
+}
+
+export const actions = {
+ async getArticles({ commit }) {
+ const response = await this.$axios.get('articles/all')
+ commit('SET_ARTICLES', response.data)
+ },
+ async getArticle({ commit }, id) {
+ const response = await this.$axios.get(`articles/${id}`)
+ commit('SET_ARTICLE', response.data)
+ },
+ async createArticle({ commit }, article) {
+ const response = await this.$axios.post('articles', article)
+ commit('SET_NEWARTICLE', response.data)
+ },
+ async updateArticle({ commit }, article) {
+ const response = await this.$axios.patch(`articles/${article._id}`, article)
+ commit('UPDATE_ARTICLE', response.data)
+ },
+ async deleteArticle({ commit }, id) {
+ await this.$axios.delete(`articles/${id}`)
+ commit('DELETE_ARTICLE', id)
+ },
+ async searchArticle({ commit }, term) {
+ const response = await this.$axios.get(
+ `articles/search/?search-term=${term}`
+ )
+ commit('SET_ARTICLES', response.data)
+ },
+ async getComments({ commit }, id) {
+ const response = await this.$axios.get(`comments/${id}`)
+ commit('SET_COMMENTS', response.data)
+ },
+ async createComment({ commit }, { id, text }) {
+ const response = await this.$axios.post(`comments/${id}`, { text })
+ commit('SET_COMMENT', response.data)
+ },
+}
+
+export const mutations = {
+ SET_ARTICLES: (state, articles) => {
+ state.articles = articles
+ },
+ SET_ARTICLE(state, article) {
+ state.article = article
+ },
+ SET_NEWARTICLE: (state, article) => {
+ state.articles = [article, ...state.articles]
+ },
+ DELETE_ARTICLE: (state, id) => {
+ state.articles = state.articles.filter((article) => article.id !== id)
+ },
+ SET_COMMENTS: (state, comments) => {
+ state.comments = comments
+ },
+ SET_COMMENT: (state, comment) => {
+ state.comments = [comment, ...state.comments]
+ },
+ UPDATE_ARTICLE: (state, updatedArticle) => {
+ const index = state.articles.findIndex(
+ (article) => article.id === updatedArticle.id
+ )
+ if (index !== -1) {
+ state.articles.splice(index, 1, updatedArticle)
+ }
+ },
+}
diff --git a/starter-project-web-vue2/store/natnaelT.js b/starter-project-web-vue2/store/natnaelT.js
new file mode 100644
index 00000000..f1c245bd
--- /dev/null
+++ b/starter-project-web-vue2/store/natnaelT.js
@@ -0,0 +1,35 @@
+const state = {
+ blogs: [],
+}
+const getters = {
+ allBlogs: (state) => state.blogs,
+}
+const actions = {
+ async fetchBlogs({ commit }) {
+ const response = await this.$axios.get('articles/all')
+ commit('setBlogs', response.data)
+ },
+ async addBlog({ commit }, blog) {
+ const response = await this.$axios.post('articles/', blog)
+ commit('newBlog', response.data)
+ },
+ async deleteBlog({ commit }, id) {
+ await this.$axios.delete(`articles/${id}`)
+ commit('removeBlog', id)
+ },
+ async updateBlog({ commit }, id) {
+ await this.$axios.patch(`articles/${id}`)
+ },
+}
+const mutations = {
+ setBlogs: (state, blogs) => (state.blogs = blogs),
+ newBlog: (state, blog) => state.blogs.unshift(blog),
+ removeBlog: (state, id) =>
+ (state.blogs = state.blogs.filter((todo) => todo.id !== id)),
+}
+export default {
+ state,
+ getters,
+ actions,
+ mutations,
+}
diff --git a/starter-project-web-vue2/store/yared.js b/starter-project-web-vue2/store/yared.js
new file mode 100644
index 00000000..e3c06883
--- /dev/null
+++ b/starter-project-web-vue2/store/yared.js
@@ -0,0 +1,44 @@
+export default {
+ namespaced: true,
+ state: {
+ blogs: [],
+ blog: {},
+ },
+ actions: {
+ async fetchBlog({ commit }, id) {
+ const res = await this.$axios.get(`articles/${id}`)
+ commit('displayBlog', res.data)
+ },
+ async fetchBlogs({ commit }) {
+ const res = await this.$axios.get('articles/all')
+ const data = res.data.reverse()
+ commit('setBlogs', data)
+ },
+ async addBlog({ commit }, newBlog) {
+ const res = await this.$axios.post('articles', newBlog)
+ commit('addBlog', res.data)
+ },
+ async deleteBlog({ commit }, id) {
+ await this.$axios.delete(`articles/${id}`)
+ commit('deleteBlog', id)
+ },
+ async updateBlog({ commit }, updBlog) {
+ const res = await this.$axios.patch(`articles/${updBlog.id}`, updBlog)
+ commit('updateBlog', res.data)
+ },
+ },
+ mutations: {
+ displayBlog: (state, blog) => (state.blog = blog),
+ setBlogs: (state, blogs) => (state.blogs = blogs),
+ addBlog: (state, blog) => state.blogs.unshift(blog),
+ deleteBlog: (state, id) =>
+ (state.blogs = state.blogs.filter((blog) => blog._id !== id)),
+ updateBlog: (state, updBlog) => {
+ const idx = state.blogs.findIndex((blog) => blog.id === updBlog.id)
+ if (idx !== -1) {
+ console.log('hi')
+ state.blogs.splice(idx, 1, updBlog)
+ }
+ },
+ },
+}
diff --git a/starter-project-web-vue2/store/yohans.js b/starter-project-web-vue2/store/yohans.js
new file mode 100644
index 00000000..8e9eb12e
--- /dev/null
+++ b/starter-project-web-vue2/store/yohans.js
@@ -0,0 +1,8 @@
+export const state = () => ({
+ blogs: [
+ { id: 1, title: 'a', content: 'content of a' },
+ { id: 2, title: 'b', content: 'content of b' },
+ { id: 3, title: 'c', content: 'content of c' },
+ { id: 4, title: 'd', content: 'content of d' },
+ ],
+})
diff --git a/starter-project-web-vue2/vercel.json b/starter-project-web-vue2/vercel.json
index e8d29499..9d3e5cee 100644
--- a/starter-project-web-vue2/vercel.json
+++ b/starter-project-web-vue2/vercel.json
@@ -1,9 +1,9 @@
{
- "builds": [
- {
- "src": "nuxt.config.js",
- "use": "@nuxtjs/vercel-builder",
- "config": {}
- }
- ]
- }
\ No newline at end of file
+ "builds": [
+ {
+ "src": "nuxt.config.js",
+ "use": "@nuxtjs/vercel-builder",
+ "config": {}
+ }
+ ]
+}