Merge branch 'master' into 상품상세_주문하기

This commit is contained in:
Sangbum Park
2022-03-10 15:13:27 +09:00
committed by GitHub
59 changed files with 1557 additions and 208 deletions

View File

@@ -0,0 +1,19 @@
import axios from "axios";
const url = process.env.VUE_APP_CUSTOMER_SERVICE_BASEURL + "/notification-service";
export default {
requestNotification() {
return axios.get(url + "/notifications");
},
patchNotification(id, isRead) {
const body = {
read: isRead
}
return axios.patch(url + "/notification/" + id, body)
},
countsNotification() {
return axios.get(url + "/api/notification/counts");
}
}

View File

@@ -1,32 +1,45 @@
import axios from "axios";
export default {
requestNearbyStore(latitude, longitude, storeName, page, size) {
const options = {
params: {
latitude: latitude,
longitude: longitude,
storeName: storeName,
page: page,
size: size
}
requestNearbyStore(latitude, longitude, storeName, page, size) {
const options = {
params: {
latitude: latitude,
longitude: longitude,
storeName: storeName,
page: page,
size: size
}
return axios.get(process.env.VUE_APP_STORE_API_URL + '/store/search', options);
},
getCategoryList(){
return axios.get(process.env.VUE_APP_CUSTOMER_SERVICE_BASEURL+'/store-service/category/');
},
fetchItem(itemId){
return axios.get(process.env.VUE_APP_STORE_API_URL+'/item/'+itemId)
},
getFavoriteStore(latitude, longitude,){
const options = {
params: {
latitude: latitude,
longitude: longitude,
}
}
return axios.get(process.env.VUE_APP_CUSTOMER_SERVICE_BASEURL+'/store-service/api/customer/store/favorite',options)
},
}
return axios.get(process.env.VUE_APP_STORE_API_URL + '/store/search', options);
},
getItemById(itemId){
return axios.get(process.env.VUE_APP_CUSTOMER_SERVICE_BASEURL+'/store-service/item/'+itemId)
},
getFavoriteStore(latitude, longitude,){
const options = {
params: {
latitude: latitude,
longitude: longitude,
}
}
return axios.get(process.env.VUE_APP_CUSTOMER_SERVICE_BASEURL+'/store-service/api/customer/store/favorite',options)
},
getCategoryList(){
return axios.get(process.env.VUE_APP_CUSTOMER_SERVICE_BASEURL+'/store-service/category/');
},
fetchItem(itemId){
return axios.get(process.env.VUE_APP_STORE_API_URL+'/item/'+itemId)
},
requestCategoriesWithItem(storeId) {
const options = {
params: {
"storeId": storeId
}
}
return axios.get(process.env.VUE_APP_STORE_API_URL + "/categories", options);
},
requestStore(storeId) {
return axios.get(process.env.VUE_APP_CUSTOMER_SERVICE_BASEURL + "/store-service/store/" + storeId);
}
}

View File

@@ -6,29 +6,43 @@
elevation="1"
>
<v-app-bar-nav-icon>
<v-icon>mdi-arrow-left</v-icon>
</v-app-bar-nav-icon>
<v-spacer></v-spacer>
<v-toolbar-title>
<v-img :src="require('@/assets/just-logo.png')"></v-img>
</v-toolbar-title>
<v-spacer></v-spacer>
<v-row class="d-flex" style="max-width: 768px;display: table; margin-left: auto; margin-right: auto; width: 100%" align="center">
<v-app-bar-nav-icon>
<v-icon>mdi-arrow-left</v-icon>
</v-app-bar-nav-icon>
<v-spacer></v-spacer>
<v-toolbar-title>
<v-img :src="require('@/assets/just-logo.png')"></v-img>
</v-toolbar-title>
<v-spacer></v-spacer>
<v-btn icon>
<v-icon>mdi-magnify</v-icon>
<v-btn
color="white"
elevation="0"
@click="goNotification"
>
<v-badge
:content="notificationCounts"
:value="notificationCounts"
color="orange"
overlap
>
<v-icon>mdi-bell-outline</v-icon>
</v-badge>
</v-btn>
</v-row>
</v-app-bar>
</template>
<script>
export default {
name: "AppNavigation"
name: "AppNavigation",
props: ["notificationCounts"],
methods: {
goNotification: function() {
this.$router.push('/notification');
}
}
}
</script>
<style scoped>
</style>

View File

@@ -0,0 +1,32 @@
<template>
<v-app-bar
app
dense
color="white"
elevation="1"
hide-on-scroll
absolute
>
<v-app-bar-nav-icon>
<v-icon>mdi-arrow-left</v-icon>
</v-app-bar-nav-icon>
<v-spacer></v-spacer>
<v-toolbar-title>
<b>{{store.name}}</b>
</v-toolbar-title>
<v-spacer></v-spacer>
<v-btn icon>
<v-icon>mdi-magnify</v-icon>
</v-btn>
</v-app-bar>
</template>
<script>
export default {
name: "StoreNavigation",
props: ["store"],
}
</script>
<style scoped>
</style>

View File

@@ -4,6 +4,7 @@ import jwt from "@/common/jwt";
import auth from "@/api/auth";
import HomeLayout from '../views/Layout/HomeLayout.vue';
import StoreLayout from "@/views/Layout/StoreLayout";
const ACCESS_TOKEN_NAME = "accessToken";
const EXPIRED_TIME_NAME = "expiredTime";
@@ -54,6 +55,11 @@ const routes = [
name: 'favorite-store',
component: () => import('../views/FavoriteStore')
},
{
path: "/notification",
name: 'notification',
component: () => import('../views/NotificationView')
},
{
path: '/login',
name: 'login',
@@ -71,8 +77,20 @@ const routes = [
},
]
},
{
path: '/store',
redirect: 'store',
beforeEnter: authCheck,
component: StoreLayout,
children: [
{
path: "/store/:storeId",
name: "store",
component: () => import('../views/StoreView'),
props: true
},
]
},
{
path: '/auth',
name: 'auth',

View File

@@ -1,9 +1,12 @@
<template>
<v-app>
<app-navigation></app-navigation>
<app-navigation
v-bind:notificationCounts="notificationCounts"></app-navigation>
<v-main>
<v-container class="px-8 py-8">
<router-view></router-view>
<router-view
v-on:plusCount="notificationCounts++"
v-on:minusCount="notificationCounts--"></router-view>
</v-container>
</v-main>
<bottom-navigation></bottom-navigation>
@@ -13,12 +16,27 @@
<script>
import AppNavigation from "../../components/AppNavigation.vue";
import BottomNavigation from "../../components/BottomNavigation.vue";
import notificationApi from "../../api/notification";
export default {
name: "HomeLayout",
components: {
'app-navigation': AppNavigation,
"bottom-navigation": BottomNavigation
},
mounted() {
this.searchNotificationCounts();
},
data: function() {
return {
notificationCounts: 0
}
},
methods: {
searchNotificationCounts: async function() {
const response = await notificationApi.countsNotification();
this.notificationCounts = response.data.data;
}
}
}
</script>

View File

@@ -0,0 +1,62 @@
<template>
<v-app>
<store-navigation
v-bind:store="store">
</store-navigation>
<v-main>
<v-container class="px-8">
<router-view
v-on:getStoreId="renderNavigation">
</router-view>
</v-container>
</v-main>
<bottom-navigation></bottom-navigation>
</v-app>
</template>
<script>
import StoreNavigation from "../../components/StoreNavigation.vue";
import BottomNavigation from "../../components/BottomNavigation.vue";
import storeApi from "../../api/store";
export default {
name: "StoreLayout",
components: {
'store-navigation': StoreNavigation,
"bottom-navigation": BottomNavigation
},
data: () => ({
store: {
id: '',
name: ''
}
}),
methods: {
renderNavigation: function(storeId) {
this.store.id = storeId;
this.getStore();
},
getStore: async function() {
if (!this.store.id) {
alert("매장 고유번호가 없습니다. 잠시후에 시도해주세요.");
return;
}
const response = await storeApi.requestStore(this.store.id);
this.store = response.data.data;
}
}
}
</script>
<style scoped>
.container {
max-width: 768px;
background-color: white;
height: 100%;
}
main {
background-color: #f2f2f2!important;
}
</style>

View File

@@ -0,0 +1,84 @@
<template>
<div>
<template
v-for="(item, index) in notifications">
<v-list-item three-line :key="item.id">
<v-list-item-content>
<v-list-item-title>{{item.title}}</v-list-item-title>
<v-list-item-subtitle>
{{item.message}}
</v-list-item-subtitle>
<v-list-item-subtitle>
2022-03-09 14:00
</v-list-item-subtitle>
</v-list-item-content>
<v-list-item-action>
<v-checkbox
disabled
v-if="item.prevRead"
v-model="item.read"
hide-details></v-checkbox>
<v-checkbox
v-else
v-model="item.read"
@click="clickRead(item.id, item.read)"
hide-details></v-checkbox>
</v-list-item-action>
</v-list-item>
<v-divider
v-if="index < notifications.length - 1"
:key="index"
></v-divider>
</template>
</div>
</template>
<script>
import notificationApi from "@/api/notification";
export default {
name: "NotificationView",
mounted() {
this.search();
},
data: function () {
return {
notifications: []
}
},
methods: {
search: async function() {
const response = await notificationApi.requestNotification();
this.render(response.data);
},
render: function(json) {
const notifications = json.data.notifications;
notifications.forEach(notification => {
this.notifications.push({
id: notification.id,
message: notification.message,
title: notification.title,
prevRead: notification.read,
read: notification.read
});
});
},
clickRead: async function(id, isRead) {
await notificationApi.patchNotification(id, isRead);
if (isRead) {
alert("해당 알림은 읽음 처리되었습니다.");
this.$emit("minusCount");
} else {
alert("해당 알림은 읽음 해제 처리되었습니다.");
this.$emit("plusCount");
}
}
}
}
</script>
<style scoped>
</style>

View File

@@ -26,7 +26,10 @@
<v-row>
<v-col v-for="card in cards" v-bind:key="card.storeId" sm="6">
<v-card v-bind:data-id="card.storeId">
<v-card
v-bind:data-id="card.storeId"
v-on:click="clickCard(card.storeId)"
>
<v-img
height="180"
:src="require('@/assets/store.jpeg')"
@@ -147,6 +150,12 @@ export default {
favoriteCounts: store.favoriteCounts
})
});
},
clickCard(storeId) {
this.$router.push({
name: "store",
params: {storeId: storeId}
})
}
}
}

View File

@@ -0,0 +1,111 @@
<template>
<div>
<div id="nav">
<v-chip-group
mandatory
center-active
show-arrows
active-class="primary--text"
v-model="tagIndex"
>
<v-chip
v-for="tag in tags"
:key="tag"
>
{{ tag }}
</v-chip>
</v-chip-group>
</div>
<br>
<div id="content">
<div v-for="category in categories" :key="category.id">
<h3 ref="focusTag">
{{ category.name }}
</h3>
<br>
<v-card
class="mx-auto mb-5"
outlined
v-for="item in category.items"
:key="item.id"
>
<v-list-item three-line>
<v-list-item-content>
<v-list-item-title class="text-h5 mb-3">
{{ item.name }}
</v-list-item-title>
<div class="text--primary mb-5">
{{ item.price }}
</div>
<v-list-item-subtitle>
</v-list-item-subtitle>
</v-list-item-content>
<v-list-item-avatar
tile
size="100"
>
<v-img :src="require('@/assets/store.jpeg')"></v-img>
</v-list-item-avatar>
</v-list-item>
</v-card>
<br>
</div>
</div>
</div>
</template>
<script>
import storeApi from "../api/store";
export default {
name: "StoreView",
props: ["storeId"],
mounted() {
if (!this.storeId) {
alert("잘못된 요청입니다.");
return;
}
this.$emit('getStoreId', this.storeId)
this.search(this.storeId);
},
data: () => ({
tags: [],
categories: [],
tagIndex: 0
}),
watch: {
tagIndex: function(newValue) {
this.$refs.focusTag[newValue].scrollIntoView({behavior: 'smooth', block: 'center'});
}
},
methods: {
search: async function(storeId) {
const response = await storeApi.requestCategoriesWithItem(storeId);
this.render(response.data);
},
render: function(json) {
this.categories = json.data.categories;
this.categories.forEach(category => {
this.tags.push(category.name);
})
},
}
}
</script>
<style scoped>
#nav {
color: white;
background-color: white;
position: sticky;
top: 0;
z-index: 999;
}
#content {
display: block !important;
z-index: -1;
}
</style>