├── .env-sample
├── .gitignore
├── LICENSE
├── README.md
├── assets
└── DEMO.gif
├── babel.config.js
├── jsconfig.json
├── package-lock.json
├── package.json
├── public
├── _redirects
├── favicon.ico
└── index.html
├── src
├── App.vue
├── assets
│ └── logo.png
├── components
│ ├── Aside.vue
│ ├── Footer.vue
│ ├── Header.vue
│ ├── Layout.vue
│ ├── SingleModal.vue
│ └── UI
│ │ ├── Alert
│ │ └── Info.vue
│ │ ├── Card
│ │ ├── AsideCard.vue
│ │ └── Card.vue
│ │ ├── Loading.vue
│ │ ├── TimelineHeader.vue
│ │ └── Widget
│ │ ├── Albums.vue
│ │ └── Filter
│ │ ├── Color.vue
│ │ ├── Filter.vue
│ │ ├── Orientation.vue
│ │ ├── SafeSearch.vue
│ │ └── Type.vue
├── main.js
├── router
│ └── index.js
├── store
│ ├── app
│ │ ├── actions.js
│ │ ├── getters.js
│ │ └── mutations.js
│ └── index.js
└── views
│ ├── CategoryView.vue
│ ├── HomeView.vue
│ ├── LoginView.vue
│ └── TagView.vue
└── vue.config.js
/.env-sample:
--------------------------------------------------------------------------------
1 | VUE_APP_PHOTOS_URL = https://pixabay.com/api/?key=YOUR_API_KEY
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | /dist
4 |
5 |
6 | # local env files
7 | .env.local
8 | .env.production
9 | .env.*.local
10 |
11 | # Log files
12 | npm-debug.log*
13 | yarn-debug.log*
14 | yarn-error.log*
15 | pnpm-debug.log*
16 |
17 | # Editor directories and files
18 | .idea
19 | .vscode
20 | *.suo
21 | *.ntvs*
22 | *.njsproj
23 | *.sln
24 | *.sw?
25 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 Emre Güney
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 | # Vue Photogram App
3 | A photo gallery app using Vue.js + Vue Router + Vuex
4 |
5 | 
6 |
7 | ## Features:
8 |
9 | - Using **[Pixabay Api](https://pixabay.com/api/)**
10 | - Home, category, tag and single photo page
11 | - Infinite scroll
12 | - Masonry layout
13 | - Filter by image type, orientation, color and safe search
14 | - Search image
15 | - List albums
16 | - Dark, light and auto mode switch
17 | - Responsive design
18 |
19 | ## Technologies and tools:
20 |
21 | - **Vue.js**
22 | - **VueX, Vue Router**
23 | - **Masonry Layout Wall**
24 | - **Pure SASS** and **SCSS**
25 | - **Responsive** design
26 |
27 | ## Project setup
28 | ```
29 | npm install
30 | ```
31 |
32 | ### Compiles and hot-reloads for development
33 | ```
34 | npm run serve
35 | ```
36 |
37 | ### Compiles and minifies for production
38 | ```
39 | npm run build
40 | ```
41 |
42 | ### Lints and fixes files
43 | ```
44 | npm run lint
45 | ```
46 |
47 | ## License:
48 |
49 | MIT License
50 |
51 | Copyright (c) 2022 Emre Güney
52 |
53 | Permission is hereby granted, free of charge, to any person obtaining a copy
54 | of this software and associated documentation files (the "Software"), to deal
55 | in the Software without restriction, including without limitation the rights
56 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
57 | copies of the Software, and to permit persons to whom the Software is
58 | furnished to do so, subject to the following conditions:
59 |
60 | The above copyright notice and this permission notice shall be included in all
61 | copies or substantial portions of the Software.
62 |
63 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
64 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
65 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
66 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
67 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
68 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
69 | SOFTWARE.
70 |
--------------------------------------------------------------------------------
/assets/DEMO.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eeguney/vue-photogram-app/3755b5687344ae418a4f69239463a68031d9969d/assets/DEMO.gif
--------------------------------------------------------------------------------
/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: [
3 | '@vue/cli-plugin-babel/preset'
4 | ]
5 | }
6 |
--------------------------------------------------------------------------------
/jsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es5",
4 | "module": "esnext",
5 | "baseUrl": "./",
6 | "moduleResolution": "node",
7 | "paths": {
8 | "@/*": [
9 | "src/*"
10 | ]
11 | },
12 | "lib": [
13 | "esnext",
14 | "dom",
15 | "dom.iterable",
16 | "scripthost"
17 | ]
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "vue-photogram-app",
3 | "version": "0.1.0",
4 | "private": true,
5 | "scripts": {
6 | "serve": "vue-cli-service serve",
7 | "build": "vue-cli-service build",
8 | "lint": "vue-cli-service lint"
9 | },
10 | "dependencies": {
11 | "@fortawesome/fontawesome-svg-core": "^6.2.0",
12 | "@fortawesome/free-brands-svg-icons": "^6.2.0",
13 | "@fortawesome/free-regular-svg-icons": "^6.2.0",
14 | "@fortawesome/free-solid-svg-icons": "^6.2.0",
15 | "@fortawesome/vue-fontawesome": "^2.0.8",
16 | "axios": "^1.1.2",
17 | "core-js": "^3.8.3",
18 | "sass": "^1.55.0",
19 | "sass-loader": "^13.1.0",
20 | "vue": "^2.6.14",
21 | "vue-masonry-wall": "^0.3.2",
22 | "vue-router": "^3.5.1",
23 | "vuex": "^3.6.2"
24 | },
25 | "devDependencies": {
26 | "@babel/core": "^7.12.16",
27 | "@babel/eslint-parser": "^7.12.16",
28 | "@vue/cli-plugin-babel": "~5.0.0",
29 | "@vue/cli-plugin-eslint": "~5.0.0",
30 | "@vue/cli-plugin-router": "~5.0.0",
31 | "@vue/cli-plugin-vuex": "~5.0.0",
32 | "@vue/cli-service": "~5.0.0",
33 | "eslint": "^7.32.0",
34 | "eslint-plugin-vue": "^8.0.3",
35 | "vue-template-compiler": "^2.6.14"
36 | },
37 | "eslintConfig": {
38 | "root": true,
39 | "env": {
40 | "node": true
41 | },
42 | "extends": [
43 | "plugin:vue/essential",
44 | "eslint:recommended"
45 | ],
46 | "parserOptions": {
47 | "parser": "@babel/eslint-parser"
48 | },
49 | "rules": {}
50 | },
51 | "browserslist": [
52 | "> 1%",
53 | "last 2 versions",
54 | "not dead"
55 | ]
56 | }
57 |
--------------------------------------------------------------------------------
/public/_redirects:
--------------------------------------------------------------------------------
1 | /* /index.html 200
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eeguney/vue-photogram-app/3755b5687344ae418a4f69239463a68031d9969d/public/favicon.ico
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | <%= htmlWebpackPlugin.options.title %>
10 |
11 |
12 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
51 |
52 |
455 |
--------------------------------------------------------------------------------
/src/assets/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eeguney/vue-photogram-app/3755b5687344ae418a4f69239463a68031d9969d/src/assets/logo.png
--------------------------------------------------------------------------------
/src/components/Aside.vue:
--------------------------------------------------------------------------------
1 |
2 |
14 |
15 |
16 |
39 |
40 |
110 |
--------------------------------------------------------------------------------
/src/components/Footer.vue:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
16 |
17 |
45 |
--------------------------------------------------------------------------------
/src/components/Header.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
12 |
13 |
22 |
23 |
28 |
31 |
32 |
33 |
34 |
35 |
36 |
46 |
47 |
48 |
58 |
59 | -
60 |
61 |
62 | -
63 |
71 |
72 | -
73 |
81 |
82 | -
83 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
144 |
145 |
307 |
--------------------------------------------------------------------------------
/src/components/Layout.vue:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
12 |
13 |
18 |
19 |
20 |
21 |
22 |
23 |
28 |
29 |
34 |
35 |
36 |
37 |
85 |
86 |
131 |
--------------------------------------------------------------------------------
/src/components/SingleModal.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
19 |
![]()
26 |
29 |
30 |
31 |
32 |
33 |
34 |
70 |
71 |
131 |
--------------------------------------------------------------------------------
/src/components/UI/Alert/Info.vue:
--------------------------------------------------------------------------------
1 |
2 | {{text}}
3 |
4 |
5 |
13 |
14 |
--------------------------------------------------------------------------------
/src/components/UI/Card/AsideCard.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 |
24 |
27 |
28 |
29 |
30 |
31 |
59 |
60 |
101 |
--------------------------------------------------------------------------------
/src/components/UI/Card/Card.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
![]()
6 |
7 |
8 |
9 |
18 |
19 |
20 |
21 | {{ data.likes }}
22 |
23 |
24 |
25 | {{ data.comments }}
26 |
27 |
28 |
29 |
30 |
31 |
59 |
60 |
125 |
--------------------------------------------------------------------------------
/src/components/UI/Loading.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
10 |
11 |
12 |
13 |
14 |
24 |
25 |
75 |
--------------------------------------------------------------------------------
/src/components/UI/TimelineHeader.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
12 |
25 |
26 |
27 | Popular
28 | Latest
29 |
30 |
31 |
32 |
33 |
43 |
44 |
89 |
--------------------------------------------------------------------------------
/src/components/UI/Widget/Albums.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
12 |
13 |
16 |
19 |
20 |
21 |
22 |
23 |
24 |
57 |
58 |
112 |
--------------------------------------------------------------------------------
/src/components/UI/Widget/Filter/Color.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
20 |
21 |
22 |
34 |
35 |
36 |
37 |
38 |
39 |
66 |
67 |
68 |
--------------------------------------------------------------------------------
/src/components/UI/Widget/Filter/Filter.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
Filter
4 |
5 |
6 |
10 |
11 |
12 |
13 |
14 |
22 |
25 |
26 |
27 |
28 |
29 |
83 |
84 |
219 |
--------------------------------------------------------------------------------
/src/components/UI/Widget/Filter/Orientation.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
23 |
24 |
25 |
26 |
27 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/src/components/UI/Widget/Filter/SafeSearch.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
17 |
18 |
19 |
20 |
21 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/src/components/UI/Widget/Filter/Type.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
15 |
16 |
17 |
18 |
19 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/src/main.js:
--------------------------------------------------------------------------------
1 | import Vue from "vue";
2 | import App from "./App.vue";
3 | import router from "./router";
4 | import store from "./store";
5 | import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome";
6 | import {
7 | faLock,
8 | faUser,
9 | faTextHeight,
10 | faLink,
11 | faImage,
12 | faBars,
13 | faImages,
14 | faSpinner,
15 | faThumbsUp,
16 | faComment,
17 | faUpDown,
18 | faLeftRight,
19 | faXmark,
20 | faRightFromBracket,
21 | faEllipsisVertical,
22 | faMoon,
23 | faSun,
24 | faFilter,
25 | } from "@fortawesome/free-solid-svg-icons";
26 | import { faSquare, faKeyboard } from "@fortawesome/free-regular-svg-icons";
27 | import { faGithub } from "@fortawesome/free-brands-svg-icons";
28 | import { library } from "@fortawesome/fontawesome-svg-core";
29 |
30 | library.add(
31 | faUser,
32 | faLock,
33 | faSquare,
34 | faTextHeight,
35 | faKeyboard,
36 | faLink,
37 | faImage,
38 | faBars,
39 | faImages,
40 | faSpinner,
41 | faThumbsUp,
42 | faComment,
43 | faUpDown,
44 | faLeftRight,
45 | faXmark,
46 | faRightFromBracket,
47 | faEllipsisVertical,
48 | faMoon,
49 | faSun,
50 | faFilter,
51 | faGithub
52 | );
53 |
54 | Vue.component("font-awesome-icon", FontAwesomeIcon);
55 |
56 | Vue.config.productionTip = false;
57 |
58 | new Vue({
59 | router,
60 | store,
61 | render: (h) => h(App),
62 | }).$mount("#app");
63 |
--------------------------------------------------------------------------------
/src/router/index.js:
--------------------------------------------------------------------------------
1 | import Vue from "vue";
2 | import VueRouter from "vue-router";
3 | import LoginView from "../views/LoginView.vue";
4 | import HomeView from "../views/HomeView.vue";
5 | import TagView from "../views/TagView.vue";
6 | import CategoryView from "../views/CategoryView.vue";
7 |
8 | Vue.use(VueRouter);
9 |
10 | const routes = [
11 | {
12 | path: "/",
13 | name: "home",
14 | component: HomeView,
15 | },
16 | {
17 | path: "/latest",
18 | name: "latest",
19 | component: HomeView,
20 | },
21 | {
22 | path: "/photo/:id",
23 | name: "photo",
24 | component: HomeView,
25 | },
26 | {
27 | path: "/tag/:tag",
28 | name: "tag",
29 | component: TagView,
30 | },
31 | {
32 | path: "/category/:category",
33 | name: "category",
34 | component: CategoryView,
35 | },
36 | {
37 | path: "/login",
38 | name: "login",
39 | component: LoginView,
40 | },
41 | ];
42 |
43 | const router = new VueRouter({
44 | mode: "history",
45 | routes,
46 | });
47 |
48 | router.beforeEach((to, from, next) => {
49 | // // clear search if exists
50 | // if (store.state.searchText != "") {
51 | // store.state.searchText = "";
52 | // }
53 | next();
54 | });
55 |
56 | export default router;
57 |
--------------------------------------------------------------------------------
/src/store/app/actions.js:
--------------------------------------------------------------------------------
1 | import Axios from "axios";
2 |
3 | let urlParameters = {
4 | q: "",
5 | imageType: "all",
6 | orientation: "all",
7 | category: null,
8 | colors: null,
9 | safesearch: "true",
10 | order: "popular",
11 | page: 1,
12 | perPage: 20,
13 | };
14 |
15 | const urlGenerator = (newUrl) => {
16 | newUrl.forEach((item) => {
17 | const { type, value } = item;
18 | urlParameters = {
19 | ...urlParameters,
20 | [type]: value,
21 | };
22 | });
23 |
24 | let URL =
25 | `${process.env.VUE_APP_PHOTOS_URL}&order=${urlParameters.order}` +
26 | `&category=${urlParameters.category}&image_type=${urlParameters.imageType}` +
27 | `&orientation=${urlParameters.orientation}&colors=${urlParameters.colors}` +
28 | `&safesearch=${urlParameters.safesearch}` +
29 | `&per_page=${urlParameters.perPage}&page=${urlParameters.page}` +
30 | `&q=${urlParameters.q}`;
31 |
32 | return URL;
33 | };
34 |
35 | export default {
36 | async fetchAll({ getters, commit }) {
37 | commit("setPhotosTimeline", null);
38 | try {
39 | const albums = [];
40 | await Promise.all([
41 | getters.getCategories.forEach((element) => {
42 | Axios.get(
43 | `${urlGenerator([
44 | { type: "perPage", value: 4 },
45 | ])}&category=${element}`
46 | ).then(({ data }) => {
47 | const { hits } = data;
48 | const album = [];
49 | hits.forEach((item) =>
50 | album.push({ [element]: { ...item, albumTitle: element } })
51 | );
52 | albums.push(album);
53 | commit("setAlbums", albums);
54 | });
55 | }),
56 | Axios.get(
57 | urlGenerator([
58 | { type: "order", value: "popular" },
59 | { type: "perPage", value: 20 },
60 | ])
61 | ).then(({ data }) => {
62 | commit("setPhotosTimeline", data.hits);
63 | }),
64 | ]);
65 | } catch (error) {
66 | console.log(error);
67 | }
68 | },
69 | async fetchPopular({ commit }) {
70 | commit("setPhotosTimeline", null);
71 | try {
72 | await Promise.all([
73 | Axios.get(
74 | urlGenerator([
75 | { type: "order", value: "popular" },
76 | { type: "perPage", value: 20 },
77 | { type: "page", value: 1 },
78 | ])
79 | ).then(({ data }) => {
80 | commit("setPhotosTimeline", data.hits);
81 | }),
82 | ]);
83 | } catch (error) {
84 | console.log(error);
85 | }
86 | },
87 | async fetchLatest({ commit }) {
88 | commit("setPhotosTimeline", null);
89 | try {
90 | await Promise.all([
91 | Axios.get(
92 | urlGenerator([
93 | { type: "order", value: "latest" },
94 | { type: "perPage", value: 20 },
95 | { type: "page", value: 1 },
96 | ])
97 | ).then(({ data }) => {
98 | commit("setPhotosTimeline", data.hits);
99 | }),
100 | ]);
101 | } catch (error) {
102 | console.log(error);
103 | }
104 | },
105 | async search({ commit }, payload) {
106 | commit("setPhotosTimeline", null);
107 | commit("setSearchText", payload);
108 | try {
109 | await Promise.all([
110 | Axios.get(
111 | urlGenerator([
112 | { type: "perPage", value: 20 },
113 | { type: "q", value: encodeURIComponent(payload) },
114 | ])
115 | ).then(({ data }) => {
116 | if (data.hits) {
117 | if (data.hits.length > 0) {
118 | commit("setPhotosTimeline", data.hits);
119 | } else commit("setPhotosTimeline", "not-found");
120 | }
121 | }),
122 | ]);
123 | } catch (error) {
124 | console.log(error);
125 | }
126 | },
127 | async filter({ commit }, payload) {
128 | commit("setPhotosTimeline", null);
129 | try {
130 | await Promise.all([
131 | Axios.get(urlGenerator(payload)).then(({ data }) => {
132 | if (data.hits) {
133 | if (data.hits.length > 0) {
134 | commit("setPhotosTimeline", data.hits);
135 | } else commit("setPhotosTimeline", null);
136 | }
137 | }),
138 | ]);
139 | } catch (error) {
140 | console.log(error);
141 | }
142 | },
143 | async fetchMore({ commit }) {
144 | commit("setFetchStatus", true);
145 | try {
146 | await Promise.all([
147 | Axios.get(
148 | urlGenerator([{ type: "page", value: urlParameters.page + 1 }])
149 | ).then(({ data }) => {
150 | if (data.hits) {
151 | if (data.hits.length > 0) {
152 | commit("morePhotosTimeline", data.hits);
153 | }
154 | }
155 | }),
156 | ]);
157 | } catch (error) {
158 | console.log(error);
159 | }
160 | },
161 | destroySearching({ commit, dispatch }) {
162 | commit("setSearchText", null);
163 | dispatch("filter", [{ type: "q", value: "" }]);
164 | },
165 | resetCategory() {
166 | urlParameters.category = null;
167 | },
168 | setdarkmode({ commit }, payload) {
169 | commit("darkmode", payload)
170 | }
171 | };
172 |
--------------------------------------------------------------------------------
/src/store/app/getters.js:
--------------------------------------------------------------------------------
1 | export default {
2 | getSignUpForm(state) {
3 | return state.signUpForm;
4 | },
5 | getCategories(state) {
6 | return state.categories;
7 | },
8 | getAlbums(state) {
9 | return state.albums;
10 | },
11 | getPhotosTimeline(state) {
12 | return state.photosTimeline;
13 | },
14 | getSearchText(state) {
15 | return state.searchText;
16 | },
17 | getFilterSection(state) {
18 | return state.filterSection;
19 | },
20 | getBackdrop(state) {
21 | return state.backdrop;
22 | },
23 | getFetchStatus(state) {
24 | return state.fetchStatus;
25 | },
26 | getDarkmode(state) {
27 | return state.darkmode;
28 | }
29 | };
30 |
--------------------------------------------------------------------------------
/src/store/app/mutations.js:
--------------------------------------------------------------------------------
1 | export default {
2 | setUsername(state, payload) {
3 | state.signUpForm = {
4 | ...state.signUpForm,
5 | username: payload,
6 | };
7 | },
8 | setPassword(state, payload) {
9 | state.signUpForm = {
10 | ...state.signUpForm,
11 | password: payload,
12 | };
13 | },
14 | setAlbums(state, payload) {
15 | state.albums = payload;
16 | },
17 | setPhotosTimeline(state, payload) {
18 | state.photosTimeline = payload;
19 | },
20 | morePhotosTimeline(state, payload) {
21 | state.photosTimeline = [...state.photosTimeline, ...payload];
22 | },
23 | setSearchText(state, payload) {
24 | state.searchText = payload;
25 | },
26 | toggleFilterSection(state) {
27 | state.filterSection = !state.filterSection;
28 | },
29 | toggleBackdrop(state) {
30 | state.backdrop = !state.backdrop;
31 | },
32 | setFetchStatus(state, payload) {
33 | state.fetchStatus = payload
34 | },
35 | darkmode(state, payload) {
36 | state.darkmode = payload
37 | }
38 | };
39 |
--------------------------------------------------------------------------------
/src/store/index.js:
--------------------------------------------------------------------------------
1 | import Vue from "vue";
2 | import Vuex from "vuex";
3 | import getters from "./app/getters";
4 | import mutations from "./app/mutations";
5 | import actions from "./app/actions";
6 |
7 | Vue.use(Vuex);
8 |
9 | export default new Vuex.Store({
10 | state: {
11 | signUpForm: {
12 | username: "",
13 | password: "",
14 | },
15 | albums: [],
16 | photosTimeline: [],
17 | searchText: "",
18 | filterSection: false,
19 | backdrop: false,
20 | fetchStatus: false,
21 | darkmode: false,
22 | categories: [
23 | "backgrounds",
24 | "fashion",
25 | "nature",
26 | "science",
27 | "people",
28 | "places",
29 | "animals",
30 | "industry",
31 | "computer",
32 | "sports",
33 | "buildings",
34 | "health",
35 | "travel",
36 | "music",
37 | ],
38 | },
39 | getters,
40 | mutations,
41 | actions,
42 | modules: {
43 | // const moduleA = {
44 | // state: () => ({ ... }),
45 | // mutations: { ... },
46 | // actions: { ... },
47 | // getters: { ... }
48 | // }
49 | // const moduleB = {
50 | // state: () => ({ ... }),
51 | // mutations: { ... },
52 | // actions: { ... }
53 | // }
54 | // const store = createStore({
55 | // modules: {
56 | // a: moduleA,
57 | // b: moduleB
58 | // }
59 | // })
60 | // store.state.a // -> `moduleA`'s state
61 | // store.state.b // -> `moduleB`'s state
62 | },
63 | });
64 |
--------------------------------------------------------------------------------
/src/views/CategoryView.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 | {{$route.params.category}}
11 |
16 |
17 |
18 |
19 |
20 |
21 |
22 | Loading...
27 |
28 |
29 |
30 |
34 |
35 |
36 |
37 |
38 |
39 |
128 |
129 |
148 |
--------------------------------------------------------------------------------
/src/views/HomeView.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
15 |
16 |
17 |
18 |
19 |
20 |
21 | Loading...
26 |
27 |
28 |
29 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
147 |
148 |
163 |
--------------------------------------------------------------------------------
/src/views/LoginView.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
78 |
79 |
80 |
81 |
105 |
106 |
217 |
--------------------------------------------------------------------------------
/src/views/TagView.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
14 |
15 |
16 |
17 |
18 |
19 |
20 | Loading...
25 |
26 |
27 |
28 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
129 |
130 |
145 |
--------------------------------------------------------------------------------
/vue.config.js:
--------------------------------------------------------------------------------
1 | const { defineConfig } = require('@vue/cli-service')
2 | module.exports = defineConfig({
3 | transpileDependencies: true
4 | })
5 |
--------------------------------------------------------------------------------