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) => ( + + ))} + + + + {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) => ( + alternative + )) + ) : ( + <> + )} +
+ ) +} + +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} + + + + + + + + + + + ) +} 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 ( +
+ + +
+ ) +} 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 @@ @@ -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 @@ - 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 @@ + + 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 @@ + + + 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 @@ + + 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 @@ + + + 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 @@ + + + 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 @@ + + + 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 @@ + + 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 @@ + + 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 @@ + + 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": {} + } + ] +}