Доделал первую версию
This commit is contained in:
		
							parent
							
								
									aa485fa2b1
								
							
						
					
					
						commit
						0fdd2cf7e0
					
				|  | @ -92,6 +92,16 @@ public function user(Request $request) | ||||||
|         return response()->json($request->user()); |         return response()->json($request->user()); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     /** | ||||||
|  |      * Get the authenticated User | ||||||
|  |      * | ||||||
|  |      * @return [json] user object | ||||||
|  |      */ | ||||||
|  |     public function username(Request $request) | ||||||
|  |     { | ||||||
|  |         return response()->json($request->user()['name']); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     /** |     /** | ||||||
|      * Logout user (Revoke the token) |      * Logout user (Revoke the token) | ||||||
|      * |      * | ||||||
|  |  | ||||||
|  | @ -4,6 +4,7 @@ | ||||||
| 
 | 
 | ||||||
| use Illuminate\Http\Request; | use Illuminate\Http\Request; | ||||||
| use App\Models\Wish; | use App\Models\Wish; | ||||||
|  | use App\Models\User; | ||||||
| 
 | 
 | ||||||
| class WishesController extends Controller | class WishesController extends Controller | ||||||
| { | { | ||||||
|  | @ -12,6 +13,19 @@ public function getUserWishes(Request $request, string $user_id) | ||||||
|         return Wish::select('id', 'name', 'price', 'url')->where('user_id', '=', $user_id)->get(); |         return Wish::select('id', 'name', 'price', 'url')->where('user_id', '=', $user_id)->get(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     public function getUsername(Request $request){ | ||||||
|  |         $request->validate([ | ||||||
|  |             'user_id' => 'required|exists:users,id' | ||||||
|  |         ]); | ||||||
|  |         $username = ['username' => User::find($request->get('user_id'))['name']]; | ||||||
|  |         return response()->json($username, 201); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public function getWishById(Request $request, string $id) | ||||||
|  |     { | ||||||
|  |         return Wish::select('id', 'name', 'price', 'url')->where('id', '=', $id)->get(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     public function create(Request $request) |     public function create(Request $request) | ||||||
|     { |     { | ||||||
|         $request->validate([ |         $request->validate([ | ||||||
|  | @ -25,15 +39,20 @@ public function create(Request $request) | ||||||
|         return response()->json($wish, 201); |         return response()->json($wish, 201); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public function update(Request $request, Wish $wish) |     public function update(Request $request) | ||||||
|     { |     { | ||||||
|         $request->validate([ |         $request->validate([ | ||||||
|  |             'id' => 'required|exists:wishes,id', | ||||||
|  |             'user_id' => 'required|exists:users,id', | ||||||
|             'name' => 'required|string|max:256', |             'name' => 'required|string|max:256', | ||||||
|             'price' => 'nullable|numeric', |             'price' => 'nullable|numeric', | ||||||
|             'url' => 'nullable|url', |             'url' => 'nullable|url', | ||||||
|         ]); |         ]); | ||||||
| 
 |         $wish = Wish::find($request->get('id')); | ||||||
|         $wish->update($request->all()); |         $wish->name = $request->get('name'); | ||||||
|  |         $wish->price = $request->get('price'); | ||||||
|  |         $wish->url = $request->get('url'); | ||||||
|  |         $wish->save(); | ||||||
|         return response()->json($wish); |         return response()->json($wish); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -0,0 +1,16 @@ | ||||||
|  | <template> | ||||||
|  |     <v-app> | ||||||
|  |         <Public></Public> | ||||||
|  |     </v-app> | ||||||
|  | </template> | ||||||
|  | 
 | ||||||
|  | <script> | ||||||
|  | import Public from "./views/Public.vue"; | ||||||
|  | 
 | ||||||
|  | export default { | ||||||
|  |     name: "PublicApp", | ||||||
|  |     components: {Public} | ||||||
|  | } | ||||||
|  | </script> | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | @ -16,3 +16,15 @@ .card-bg { | ||||||
|     background-color: #212022!important; |     background-color: #212022!important; | ||||||
|     color: white!important; |     color: white!important; | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | a:link { | ||||||
|  |     color: aqua; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | a:visited { | ||||||
|  |     color: darkorange; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | a:active { | ||||||
|  |     color: crimson; | ||||||
|  | } | ||||||
|  | @ -5,5 +5,11 @@ export const rules = { | ||||||
|     }, |     }, | ||||||
|     notNull: value => { |     notNull: value => { | ||||||
|         return (value !== null && value !== undefined && value !== '') || 'Поле не может быть пустым'; |         return (value !== null && value !== undefined && value !== '') || 'Поле не может быть пустым'; | ||||||
|  |     }, | ||||||
|  |     id: value => { | ||||||
|  |         return (value !== null && value !== undefined && typeof value == 'number') || 'Неверный id'; | ||||||
|  |     }, | ||||||
|  |     price: value => { | ||||||
|  |         return (typeof value == 'number' || typeof value == 'undefined' || value === null) || 'Стоимость должна быть числом'; | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -0,0 +1,19 @@ | ||||||
|  | import './js/bootstrap'; | ||||||
|  | import {createApp} from 'vue' | ||||||
|  | import PublicApp from './PublicApp.vue'; | ||||||
|  | import { createVuetify } from 'vuetify' | ||||||
|  | import 'vuetify/styles' | ||||||
|  | import * as components from 'vuetify/components' | ||||||
|  | import * as directives from 'vuetify/directives' | ||||||
|  | import '@mdi/font/css/materialdesignicons.css' | ||||||
|  | import { createMemoryHistory, createRouter } from 'vue-router' | ||||||
|  | import {createPinia} from "pinia"; | ||||||
|  | 
 | ||||||
|  | const vuetify = createVuetify({ | ||||||
|  |     components, | ||||||
|  |     directives | ||||||
|  | }) | ||||||
|  | 
 | ||||||
|  | const pinia = createPinia() | ||||||
|  | 
 | ||||||
|  | createApp(PublicApp).use(vuetify).use(pinia).mount("#app") | ||||||
|  | @ -82,6 +82,20 @@ export const useUserStore = defineStore('user', { | ||||||
|         nullifyUser() { |         nullifyUser() { | ||||||
|             this.setUser(null); |             this.setUser(null); | ||||||
|             this.setToken(null); |             this.setToken(null); | ||||||
|  |         }, | ||||||
|  |         async getUsername(id){ | ||||||
|  |             let result = null; | ||||||
|  |             await axios.get('/api/wish/username', | ||||||
|  |                 { | ||||||
|  |                     params: | ||||||
|  |                         { | ||||||
|  |                             user_id: id | ||||||
|  |                         } | ||||||
|  |                 } | ||||||
|  |             ).then((res) => { | ||||||
|  |                 result = res; | ||||||
|  |             }); | ||||||
|  |             return result; | ||||||
|         } |         } | ||||||
|     }, |     }, | ||||||
| }) | }) | ||||||
|  |  | ||||||
|  | @ -57,6 +57,39 @@ export const useWishStore = defineStore('wish', { | ||||||
|             ).then((response)=>{ |             ).then((response)=>{ | ||||||
|                 return response; |                 return response; | ||||||
|             }); |             }); | ||||||
|         } |         }, | ||||||
|  |         async update(id, user_id, name, price, url, token){ | ||||||
|  |             await axios.post(`/api/wish/update`, | ||||||
|  |                 { | ||||||
|  |                     id: id, | ||||||
|  |                     user_id: user_id, | ||||||
|  |                     name: name, | ||||||
|  |                     price: price, | ||||||
|  |                     url: url | ||||||
|  |                 }, | ||||||
|  |                 { | ||||||
|  |                     headers: { | ||||||
|  |                         Authorization: `Bearer ${token}`, | ||||||
|  |                         token: token | ||||||
|  |                     }, | ||||||
|  |                 } | ||||||
|  |             ).then((response)=>{ | ||||||
|  |                 return response; | ||||||
|  |             }); | ||||||
|  |         }, | ||||||
|  |         async getWishById(id, token){ | ||||||
|  |             let result = null; | ||||||
|  |             await axios.get(`/api/wish/by_id/${id.toString()}`, | ||||||
|  |                 { | ||||||
|  |                     headers: { | ||||||
|  |                         Authorization: `Bearer ${token}`, | ||||||
|  |                         token: token | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             ).then((response)=>{ | ||||||
|  |                 result = response.data; | ||||||
|  |             }); | ||||||
|  |             return result; | ||||||
|  |         }, | ||||||
|     }, |     }, | ||||||
| }) | }) | ||||||
|  |  | ||||||
|  | @ -17,7 +17,8 @@ export default { | ||||||
|         rememberMe: false, |         rememberMe: false, | ||||||
|         errorMessage: '', |         errorMessage: '', | ||||||
|         errorMessageContainerStyle: '', |         errorMessageContainerStyle: '', | ||||||
|         showPassword: false |         showPassword: false, | ||||||
|  |         loading: false | ||||||
|     }), |     }), | ||||||
|     methods: { |     methods: { | ||||||
|         validate(){ |         validate(){ | ||||||
|  | @ -32,12 +33,14 @@ export default { | ||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
|         loginAction(){ |         loginAction(){ | ||||||
|  |             this.loading = true; | ||||||
|             let validation = this.validate(); |             let validation = this.validate(); | ||||||
|             if (validation !== true){ |             if (validation !== true){ | ||||||
|                 alert(validation); |                 alert(validation); | ||||||
|                 return; |                 return; | ||||||
|             } |             } | ||||||
|             this.userStore.login(this.email, this.password, this.rememberMe).then((isLogged) => { |             this.userStore.login(this.email, this.password, this.rememberMe).then((isLogged) => { | ||||||
|  |                 this.loading = false; | ||||||
|                 if (typeof isLogged == "boolean") { |                 if (typeof isLogged == "boolean") { | ||||||
|                     if (isLogged){ |                     if (isLogged){ | ||||||
|                         this.errorMessage = ''; |                         this.errorMessage = ''; | ||||||
|  | @ -83,7 +86,7 @@ export default { | ||||||
|             <v-checkbox v-model="rememberMe" label="Запомнить меня"></v-checkbox> |             <v-checkbox v-model="rememberMe" label="Запомнить меня"></v-checkbox> | ||||||
|         </div> |         </div> | ||||||
|         <v-label :style="errorMessageContainerStyle">{{ errorMessage }}</v-label> |         <v-label :style="errorMessageContainerStyle">{{ errorMessage }}</v-label> | ||||||
|         <v-btn @click="this.loginAction">Войти</v-btn> |         <v-btn @click="this.loginAction" :loading="loading">Войти</v-btn> | ||||||
|     </div> |     </div> | ||||||
| </template> | </template> | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -14,7 +14,8 @@ export default { | ||||||
|         errorMessage: '', |         errorMessage: '', | ||||||
|         errorMessageContainerStyle: 'display: none;', |         errorMessageContainerStyle: 'display: none;', | ||||||
|         showPassword: false, |         showPassword: false, | ||||||
|         showRepeatPassword: false |         showRepeatPassword: false, | ||||||
|  |         loading: false | ||||||
|     }), |     }), | ||||||
|     computed: { |     computed: { | ||||||
|         rules() { |         rules() { | ||||||
|  | @ -37,12 +38,14 @@ export default { | ||||||
|             return check === null ? true : check; |             return check === null ? true : check; | ||||||
|         }, |         }, | ||||||
|         registrationAction(){ |         registrationAction(){ | ||||||
|  |             this.loading = true; | ||||||
|             let validation = this.validate(); |             let validation = this.validate(); | ||||||
|             if (validation !== true){ |             if (validation !== true){ | ||||||
|                 alert(validation); |                 alert(validation); | ||||||
|                 return; |                 return; | ||||||
|             } |             } | ||||||
|             this.userStore.registration(this.login, this.email, this.password, this.repeatPassword).then((isRegistred)=>{ |             this.userStore.registration(this.login, this.email, this.password, this.repeatPassword).then((isRegistred)=>{ | ||||||
|  |                 this.loading = false; | ||||||
|                 if (typeof isRegistred == "boolean") { |                 if (typeof isRegistred == "boolean") { | ||||||
|                     if (isRegistred){ |                     if (isRegistred){ | ||||||
|                         this.errorMessage = ''; |                         this.errorMessage = ''; | ||||||
|  | @ -100,7 +103,7 @@ export default { | ||||||
|                       required |                       required | ||||||
|         ></v-text-field> |         ></v-text-field> | ||||||
|         <v-label :style="errorMessageContainerStyle">{{ errorMessage }}</v-label> |         <v-label :style="errorMessageContainerStyle">{{ errorMessage }}</v-label> | ||||||
|         <v-btn @click="this.registrationAction">Регистрация</v-btn> |         <v-btn @click="this.registrationAction" :loading="loading">Регистрация</v-btn> | ||||||
|     </div> |     </div> | ||||||
| <!--    <v-form v-model="valid"  @submit.prevent>--> | <!--    <v-form v-model="valid"  @submit.prevent>--> | ||||||
| <!--        --> | <!--        --> | ||||||
|  |  | ||||||
|  | @ -0,0 +1,36 @@ | ||||||
|  | <template> | ||||||
|  |     <v-card class="bg-gradient" style="height: 100%"> | ||||||
|  |         <v-card-text class="d-flex justify-center align-center"> | ||||||
|  |             <v-card class="align-center justify-center h-auto w-66 card-bg"> | ||||||
|  |                 <v-card-title class="d-flex justify-space-between"> | ||||||
|  |                     <div> | ||||||
|  |                         <span>Добро пожаловать в </span> | ||||||
|  |                         <span><a href="/" class="link-no-decor">Wishlist</a></span> | ||||||
|  |                     </div> | ||||||
|  |                 </v-card-title> | ||||||
|  |                 <v-card-text class="d-flex justify-center align-center h-auto"> | ||||||
|  |                     <ShowWhishlist/> | ||||||
|  |                 </v-card-text> | ||||||
|  |             </v-card> | ||||||
|  |         </v-card-text> | ||||||
|  |     </v-card> | ||||||
|  | </template> | ||||||
|  | 
 | ||||||
|  | <script> | ||||||
|  | import ShowWhishlist from "./PublicWishlist/ShowWhishlist.vue"; | ||||||
|  | export default { | ||||||
|  |     name: "Public", | ||||||
|  |     components: {ShowWhishlist} | ||||||
|  | } | ||||||
|  | </script> | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | <style scoped> | ||||||
|  | 
 | ||||||
|  | .bg-gradient { | ||||||
|  |     background: linear-gradient(-45deg, #000610, #000f25, #00152f); | ||||||
|  |     background-size: 100% 100%; | ||||||
|  |     height: 100vh; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | </style> | ||||||
|  | @ -0,0 +1,54 @@ | ||||||
|  | <script> | ||||||
|  | import { useWishStore } from "../../store/wish.js"; | ||||||
|  | import { useUserStore } from "../../store/user.js"; | ||||||
|  | export default { | ||||||
|  |     name: "ShowWhishlist", | ||||||
|  |     data: () => ({ | ||||||
|  |         wishes: [], | ||||||
|  |         wishStore: useWishStore(), | ||||||
|  |         userStore: useUserStore(), | ||||||
|  |         fetching: false, | ||||||
|  |         username: '' | ||||||
|  |     }), | ||||||
|  |     mounted() { | ||||||
|  |         let urlArray = window.location.href.split('/'); | ||||||
|  |         let user_id = urlArray[urlArray.length - 1]; | ||||||
|  |         this.fetching = true; | ||||||
|  |         this.userStore.getUsername(user_id).then((res)=>{ | ||||||
|  |             console.log(res); | ||||||
|  |             this.username = res.data.username; | ||||||
|  |             this.wishStore.getUserWishes(user_id).then((responce)=>{ | ||||||
|  |                 this.wishes = responce; | ||||||
|  |                 this.fetching = false; | ||||||
|  |             }); | ||||||
|  |         }); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | </script> | ||||||
|  | 
 | ||||||
|  | <template> | ||||||
|  |     <v-skeleton-loader color="grey-darken-4" type="table" v-if="fetching"></v-skeleton-loader> | ||||||
|  |     <v-table v-else class="card-bg w-100 h-auto mt-5 pa-3"> | ||||||
|  |         <thead> | ||||||
|  |             <tr> | ||||||
|  |                 <th colspan="3" class="text-center text-h5">Список пользователя {{ this.username }}</th> | ||||||
|  |             </tr> | ||||||
|  |             <tr> | ||||||
|  |                 <th class="text-subtitle-1">Наименование</th> | ||||||
|  |                 <th class="text-subtitle-1">Цена</th> | ||||||
|  |                 <th class="text-subtitle-1">Ссылка</th> | ||||||
|  |             </tr> | ||||||
|  |         </thead> | ||||||
|  |         <tbody> | ||||||
|  |             <tr v-for="wish in wishes"> | ||||||
|  |                 <td>{{ wish['name'] }}</td> | ||||||
|  |                 <td>{{ wish['price'] }}</td> | ||||||
|  |                 <td><a target="_blank" :href="wish['url']">{{ wish['url'] }}</a></td> | ||||||
|  |             </tr> | ||||||
|  |         </tbody> | ||||||
|  |     </v-table> | ||||||
|  | </template> | ||||||
|  | 
 | ||||||
|  | <style scoped> | ||||||
|  | 
 | ||||||
|  | </style> | ||||||
|  | @ -12,7 +12,8 @@ | ||||||
|                     <span v-if="isAuthenticated" class="link-no-decor align-end" @click="logout">Выйти</span> |                     <span v-if="isAuthenticated" class="link-no-decor align-end" @click="logout">Выйти</span> | ||||||
|                 </v-card-title> |                 </v-card-title> | ||||||
|                 <v-card-text class="d-flex justify-center align-center"> |                 <v-card-text class="d-flex justify-center align-center"> | ||||||
|                     <router-view/> |                     <v-skeleton-loader class="w-100" color="grey-darken-4" type="card" v-if="fetchingUser"></v-skeleton-loader> | ||||||
|  |                     <router-view v-else/> | ||||||
|                 </v-card-text> |                 </v-card-text> | ||||||
|             </v-card> |             </v-card> | ||||||
|         </v-card-text> |         </v-card-text> | ||||||
|  | @ -26,7 +27,8 @@ export default { | ||||||
|     name: "Welcome", |     name: "Welcome", | ||||||
|     data: () => ({ |     data: () => ({ | ||||||
|         isAuthenticated: false, |         isAuthenticated: false, | ||||||
|         userStore: useUserStore() |         userStore: useUserStore(), | ||||||
|  |         fetchingUser: false | ||||||
|     }), |     }), | ||||||
|     computed: { |     computed: { | ||||||
|         user() { |         user() { | ||||||
|  | @ -40,9 +42,11 @@ export default { | ||||||
|         } |         } | ||||||
|     }, |     }, | ||||||
|     mounted() { |     mounted() { | ||||||
|  |         this.fetchingUser = true; | ||||||
|         this.$router.push('/auth_options'); |         this.$router.push('/auth_options'); | ||||||
|         watch(this.userStore, (newStore, oldStore)=>{ |         watch(this.userStore, (newStore, oldStore)=>{ | ||||||
|             this.isAuthenticated = newStore.user !== null && newStore.user !== undefined; |             this.isAuthenticated = newStore.user !== null && newStore.user !== undefined; | ||||||
|  |             this.fetchingUser = false; | ||||||
|             if (this.isAuthenticated) { |             if (this.isAuthenticated) { | ||||||
|                 this.$router.push('/wishlist'); |                 this.$router.push('/wishlist'); | ||||||
|             } else { |             } else { | ||||||
|  |  | ||||||
|  | @ -9,7 +9,8 @@ export default { | ||||||
|         wishStore: useWishStore(), |         wishStore: useWishStore(), | ||||||
|         name: null, |         name: null, | ||||||
|         price: null, |         price: null, | ||||||
|         url: null |         url: null, | ||||||
|  |         creating: false | ||||||
|     }), |     }), | ||||||
|     computed: { |     computed: { | ||||||
|         rules() { |         rules() { | ||||||
|  | @ -22,15 +23,33 @@ export default { | ||||||
|     }, |     }, | ||||||
|     methods: { |     methods: { | ||||||
|         validate(){ |         validate(){ | ||||||
|             return rules.notNull(this.name); |             if (this.price == ''){ | ||||||
|  |                 this.price = null; | ||||||
|  |             } | ||||||
|  |             if (typeof this.price == 'string' && /^\d+[\.,\,]?\d+$/.test(this.price)){ | ||||||
|  |                 this.price = parseFloat(this.price) | ||||||
|  |             } | ||||||
|  |             let validateName = rules.notNull(this.name); | ||||||
|  |             let validatePrice = rules.price(this.price); | ||||||
|  |             let check = null; | ||||||
|  |             let valid = [validateName, validatePrice]; | ||||||
|  |             valid.forEach((element)=>{ | ||||||
|  |                 if (typeof element !== "boolean"){ | ||||||
|  |                     check = element; | ||||||
|  |                 } | ||||||
|  |             }); | ||||||
|  |             return check === null ? true : check; | ||||||
|         }, |         }, | ||||||
|         createWish(){ |         createWish(){ | ||||||
|  |             this.creating = true; | ||||||
|             let validation = this.validate(); |             let validation = this.validate(); | ||||||
|             if (typeof validation !== "boolean"){ |             if (typeof validation !== "boolean"){                 | ||||||
|  |                 this.creating = false; | ||||||
|                 alert(validation); |                 alert(validation); | ||||||
|                 return; |                 return; | ||||||
|             } |             } | ||||||
|             this.wishStore.create(this.userStore.user['id'], this.name, this.price, this.url, this.userStore.token).then(()=>{ |             this.wishStore.create(this.userStore.user['id'], this.name, this.price, this.url, this.userStore.token).then(()=>{ | ||||||
|  |                 this.creating = false; | ||||||
|                 this.updateFrontWishes(); |                 this.updateFrontWishes(); | ||||||
|                 this.dialogCreate(); |                 this.dialogCreate(); | ||||||
|             }); |             }); | ||||||
|  | @ -51,7 +70,7 @@ export default { | ||||||
|             <v-text-field class="w-100" label="Наименование" v-model="name" :rules="[rules.notNull]"></v-text-field> |             <v-text-field class="w-100" label="Наименование" v-model="name" :rules="[rules.notNull]"></v-text-field> | ||||||
|             <v-text-field class="w-100" label="Стоимость" v-model="price"></v-text-field> |             <v-text-field class="w-100" label="Стоимость" v-model="price"></v-text-field> | ||||||
|             <v-text-field class="w-100" label="Ссылка" v-model="url"></v-text-field> |             <v-text-field class="w-100" label="Ссылка" v-model="url"></v-text-field> | ||||||
|             <v-btn class="w-33" @click="createWish">Создать</v-btn> |             <v-btn class="w-33" @click="createWish" :loading="creating">Создать</v-btn> | ||||||
|         </v-card-text> |         </v-card-text> | ||||||
|     </v-card> |     </v-card> | ||||||
| </template> | </template> | ||||||
|  |  | ||||||
|  | @ -0,0 +1,99 @@ | ||||||
|  | <script> | ||||||
|  | import {useUserStore} from "../../store/user.js"; | ||||||
|  | import {useWishStore} from "../../store/wish.js"; | ||||||
|  | import {rules} from "../../js/rules.js"; | ||||||
|  | import {watch} from "vue"; | ||||||
|  | import {toRef, ref} from "vue"; | ||||||
|  | 
 | ||||||
|  | export default { | ||||||
|  |     name: "EditWish", | ||||||
|  |     props: { | ||||||
|  |         dialogEdit: Function, | ||||||
|  |         updateFrontWishes: Function, | ||||||
|  |         wish_id: Number | ||||||
|  |     }, | ||||||
|  |     data: () => ({ | ||||||
|  |         userStore: useUserStore(), | ||||||
|  |         wishStore: useWishStore(), | ||||||
|  |         name: null, | ||||||
|  |         price: null, | ||||||
|  |         url: null, | ||||||
|  |         fetching: true, | ||||||
|  |         updating: false | ||||||
|  |     }), | ||||||
|  |     computed: { | ||||||
|  |         rules() { | ||||||
|  |             return rules | ||||||
|  |         } | ||||||
|  |     }, | ||||||
|  |     setup(props) { | ||||||
|  |         const id = toRef(props, 'wish_id') | ||||||
|  |     }, | ||||||
|  |     methods: { | ||||||
|  |         validate(){ | ||||||
|  |             if (this.price == ""){ | ||||||
|  |                 this.price = null; | ||||||
|  |             } | ||||||
|  |             if (typeof this.price == 'string' && /^\d+[\.,\,]?\d+$/.test(this.price)){ | ||||||
|  |                 this.price = parseFloat(this.price) | ||||||
|  |             } | ||||||
|  |             let validateId = rules.id(this.wish_id); | ||||||
|  |             let validateName = rules.notNull(this.name); | ||||||
|  |             let validatePrice = rules.price(this.price); | ||||||
|  |             let check = null; | ||||||
|  |             let valid = [validateId, validateName, validatePrice]; | ||||||
|  |             valid.forEach((element)=>{ | ||||||
|  |                 if (typeof element !== "boolean"){ | ||||||
|  |                     check = element; | ||||||
|  |                 } | ||||||
|  |             }); | ||||||
|  |             return check === null ? true : check; | ||||||
|  |         }, | ||||||
|  |         editWish(){ | ||||||
|  |             this.updating = true; | ||||||
|  |             let validation = this.validate(); | ||||||
|  |             if (typeof validation !== "boolean"){ | ||||||
|  |                 console.log(this.price); | ||||||
|  |                 this.updating = false; | ||||||
|  |                 alert(validation); | ||||||
|  |                 return; | ||||||
|  |             } | ||||||
|  |             this.wishStore.update(this.wish_id, this.userStore.user['id'], this.name, this.price, this.url, this.userStore.token).then(()=>{ | ||||||
|  |                 this.updating = false; | ||||||
|  |                 this.updateFrontWishes(); | ||||||
|  |                 this.dialogEdit(); | ||||||
|  |             }); | ||||||
|  |         } | ||||||
|  |     }, | ||||||
|  |     mounted() { | ||||||
|  |         this.wishStore.getWishById(this.wish_id, this.userStore.token).then((response)=>{ | ||||||
|  |             this.name = response[0]['name']; | ||||||
|  |             this.price = response[0]['price']; | ||||||
|  |             this.url = response[0]['url']; | ||||||
|  |             this.fetching = false; | ||||||
|  |         }) | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | </script> | ||||||
|  | 
 | ||||||
|  | <template> | ||||||
|  |     <v-skeleton-loader color="grey-darken-4" type="card" v-if="fetching"></v-skeleton-loader> | ||||||
|  |     <v-card class="card-bg" v-else> | ||||||
|  |         <v-card-title class="d-flex justify-space-between"> | ||||||
|  |             <span>Редактирование элемента</span> | ||||||
|  |             <span> | ||||||
|  |                 <v-icon @click="dialogEdit" class="cursor-pointer" color="white" icon="mdi-close-thick"></v-icon> | ||||||
|  |             </span> | ||||||
|  |         </v-card-title> | ||||||
|  |         <v-card-text class="d-flex align-center flex-column w-100"> | ||||||
|  |             <v-text-field class="w-100" label="Наименование" v-model="name" :rules="[rules.notNull]"></v-text-field> | ||||||
|  |             <v-text-field class="w-100" label="Стоимость" v-model="price"></v-text-field> | ||||||
|  |             <v-text-field class="w-100" label="Ссылка" v-model="url"></v-text-field> | ||||||
|  |             <v-btn :loading="updating" class="w-33" @click="editWish">Сохранить</v-btn> | ||||||
|  |         </v-card-text> | ||||||
|  |     </v-card> | ||||||
|  | </template> | ||||||
|  | 
 | ||||||
|  | <style scoped> | ||||||
|  | 
 | ||||||
|  | </style> | ||||||
|  | @ -3,20 +3,25 @@ import {useUserStore} from "../../store/user.js"; | ||||||
| import {useWishStore} from "../../store/wish.js"; | import {useWishStore} from "../../store/wish.js"; | ||||||
| import CreateWish from "./CreateWish.vue"; | import CreateWish from "./CreateWish.vue"; | ||||||
| import {ref} from "vue"; | import {ref} from "vue"; | ||||||
|  | import EditWish from "./EditWish.vue"; | ||||||
| export default { | export default { | ||||||
|     name: "Wishlist", |     name: "Wishlist", | ||||||
|     components: {CreateWish}, |     components: {EditWish, CreateWish}, | ||||||
|     data: () => ({ |     data: () => ({ | ||||||
|         userStore: useUserStore(), |         userStore: useUserStore(), | ||||||
|         wishStore: useWishStore(), |         wishStore: useWishStore(), | ||||||
|         wishesList: [], |         wishesList: [], | ||||||
|         fetching: true, |         fetching: true, | ||||||
|         dialogCreate: ref(false), |         dialogCreate: ref(false), | ||||||
|         dialogEdit: ref(false) |         dialogEdit: ref(false), | ||||||
|  |         wishToEditId: ref(0), | ||||||
|  |         wishlistLink: '', | ||||||
|  |         snackbar: false | ||||||
|     }), |     }), | ||||||
|     mounted() { |     mounted() { | ||||||
|         this.wishStore.getUserWishes(this.userStore.user['id']).then((wishes)=>{ |         this.wishStore.getUserWishes(this.userStore.user['id']).then((wishes)=>{ | ||||||
|             this.wishesList = wishes; |             this.wishesList = wishes; | ||||||
|  |             this.wishlistLink = window.location.origin + '/wishlist/' + this.userStore.user['id']; | ||||||
|             this.fetching = false |             this.fetching = false | ||||||
|         }); |         }); | ||||||
|     }, |     }, | ||||||
|  | @ -44,44 +49,64 @@ export default { | ||||||
|             }) |             }) | ||||||
|         }, |         }, | ||||||
|         editWish(id){ |         editWish(id){ | ||||||
| 
 |             this.wishToEditId = id; | ||||||
|  |             this.dialogEdit = true; | ||||||
|         }, |         }, | ||||||
|         createWish(){ |         getWishToEditId(){ | ||||||
| 
 |             return this.wishToEditId; | ||||||
|  |         }, | ||||||
|  |         copyLink(){ | ||||||
|  |             navigator.clipboard.writeText(this.wishlistLink); | ||||||
|  |             this.snackbar = true; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
| </script> | </script> | ||||||
| 
 | 
 | ||||||
| <template> | <template> | ||||||
| <!--    <v-label class="link-no-decor" @click="this.tryWishes">Hello world!</v-label>--> |     <div class="d-flex flex-column"> | ||||||
|     <v-skeleton-loader color="grey-darken-4" type="table" v-if="fetching"></v-skeleton-loader> |         <v-skeleton-loader color="grey-darken-4" type="table" v-if="fetching"></v-skeleton-loader> | ||||||
|     <v-table v-else class="card-bg w-100 h-auto mt-5 pa-3"> |         <div v-if="!fetching" class="d-flex justify-center align-center w-100 pt-5"> | ||||||
|         <thead> |             <v-text-field  | ||||||
|             <tr> |                 class="w-33"  | ||||||
|                 <th>Наименование</th> |                 append-inner-icon="mdi-content-copy"  | ||||||
|                 <th>Цена</th> |                 @click:append-inner="copyLink" | ||||||
|                 <th>Ссылка</th> |                 readonly | ||||||
|                 <th></th> |             > | ||||||
|                 <th></th> |             {{ wishlistLink }} | ||||||
|             </tr> |             </v-text-field> | ||||||
|         </thead> |             <v-snackbar v-model="snackbar">Текст скопирован!</v-snackbar> | ||||||
|         <tbody> |         </div> | ||||||
|             <tr v-for="wish in wishesList"> |         <v-table v-if="!fetching" class="card-bg w-100 h-auto mt-5 pa-3"> | ||||||
|                 <td>{{ wish['name'] }}</td> |             <thead> | ||||||
|                 <td>{{ wish['price'] }}</td> |                 <tr> | ||||||
|                 <td><a target="_blank" :href="wish['url']">{{ wish['url'] }}</a></td> |                     <th class="text-subtitle-1">Наименование</th> | ||||||
|                 <td><v-icon @click="" class="cursor-pointer" color="white" icon="mdi-pencil"></v-icon></td> |                     <th class="text-subtitle-1">Цена</th> | ||||||
|                 <td><v-icon @click="removeWish(wish['id'])" class="cursor-pointer" color="white" icon="mdi-trash-can"></v-icon></td> |                     <th class="text-subtitle-1">Ссылка</th> | ||||||
|             </tr> |                     <th class="text-subtitle-1"></th> | ||||||
|             <tr class="text-center"> |                     <th class="text-subtitle-1"></th> | ||||||
|                 <td colspan="5"><v-btn @click="dialogCreate = true" color="#212022" elevation="0" block><v-icon class="cursor-pointer" icon="mdi-plus-thick"></v-icon></v-btn></td> |                 </tr> | ||||||
|             </tr> |             </thead> | ||||||
|         </tbody> |             <tbody> | ||||||
|         <v-dialog v-model="dialogCreate" class="w-66"> |                 <tr v-for="wish in wishesList"> | ||||||
|             <CreateWish :dialogCreate="dialogCreateClose" :updateFrontWishes="updateFrontWishes"/> |                     <td>{{ wish['name'] }}</td> | ||||||
|         </v-dialog> |                     <td>{{ wish['price'] }}</td> | ||||||
|     </v-table> |                     <td><a target="_blank" :href="wish['url']">{{ wish['url'] }}</a></td> | ||||||
|  |                     <td><v-icon @click="editWish(wish['id'])" class="cursor-pointer" color="white" icon="mdi-pencil"></v-icon></td> | ||||||
|  |                     <td><v-icon @click="removeWish(wish['id'])" class="cursor-pointer" color="white" icon="mdi-trash-can"></v-icon></td> | ||||||
|  |                 </tr> | ||||||
|  |                 <tr class="text-center"> | ||||||
|  |                     <td colspan="5"><v-btn @click="dialogCreate = true" color="#212022" elevation="0" block><v-icon class="cursor-pointer" icon="mdi-plus-thick"></v-icon></v-btn></td> | ||||||
|  |                 </tr> | ||||||
|  |             </tbody> | ||||||
|  |             <v-dialog v-model="dialogCreate" class="w-66"> | ||||||
|  |                 <CreateWish :dialogCreate="dialogCreateClose" :updateFrontWishes="updateFrontWishes"/> | ||||||
|  |             </v-dialog> | ||||||
|  |             <v-dialog v-model="dialogEdit" class="w-66"> | ||||||
|  |                 <EditWish :dialogEdit="dialogEditClose" :updateFrontWishes="updateFrontWishes" :wish_id="wishToEditId"/> | ||||||
|  |             </v-dialog> | ||||||
|  |         </v-table> | ||||||
|  |     </div> | ||||||
| </template> | </template> | ||||||
| 
 | 
 | ||||||
| <style scoped> | <style scoped> | ||||||
|  |  | ||||||
|  | @ -0,0 +1,14 @@ | ||||||
|  | <!DOCTYPE html> | ||||||
|  | <html lang="{{ str_replace('_', '-', app()->getLocale()) }}"> | ||||||
|  |     <head> | ||||||
|  |         <meta charset="utf-8"> | ||||||
|  |         <meta name="viewport" content="width=device-width, initial-scale=1"> | ||||||
|  |         <title>Wishlist</title> | ||||||
|  |         <link rel="icon" href="/images/favicon.svg" sizes="any" type="image/svg+xml"> | ||||||
|  |         @vite('resources/publicWishlist.js') | ||||||
|  |         @vite('resources/css/app.css') | ||||||
|  |     </head> | ||||||
|  |     <body class="antialiased"> | ||||||
|  |         <div id="app"></div> | ||||||
|  |     </body> | ||||||
|  | </html> | ||||||
|  | @ -31,10 +31,12 @@ | ||||||
| }); | }); | ||||||
| 
 | 
 | ||||||
| Route::group(['prefix' => 'wish'], function () { | Route::group(['prefix' => 'wish'], function () { | ||||||
|  |     Route::get('username', [WishesController::class, 'getUsername']); | ||||||
|     Route::get('user_wishes/{user_id}', [WishesController::class, 'getUserWishes']); |     Route::get('user_wishes/{user_id}', [WishesController::class, 'getUserWishes']); | ||||||
|     Route::group(['middleware' => 'auth:sanctum'], function() { |     Route::group(['middleware' => 'auth:sanctum'], function() { | ||||||
|         Route::post('create', [WishesController::class, 'create']); |         Route::post('create', [WishesController::class, 'create']); | ||||||
|         Route::post('update', [WishesController::class, 'update']); |         Route::post('update', [WishesController::class, 'update']); | ||||||
|         Route::post('destroy', [WishesController::class, 'destroy']); |         Route::post('destroy', [WishesController::class, 'destroy']); | ||||||
|  |         Route::get('by_id/{id}', [WishesController::class, 'getWishById']); | ||||||
|     }); |     }); | ||||||
| }); | }); | ||||||
|  |  | ||||||
|  | @ -16,3 +16,7 @@ | ||||||
| Route::get('/', function () { | Route::get('/', function () { | ||||||
|     return view('welcome'); |     return view('welcome'); | ||||||
| }); | }); | ||||||
|  | 
 | ||||||
|  | Route::get('/wishlist/{user_id}', function () { | ||||||
|  |     return view('public'); | ||||||
|  | }); | ||||||
|  |  | ||||||
|  | @ -6,7 +6,7 @@ export default defineConfig({ | ||||||
|     plugins: [ |     plugins: [ | ||||||
|         vue(), |         vue(), | ||||||
|         laravel({ |         laravel({ | ||||||
|             input: ['resources/css/app.css', 'resources/app.js'], |             input: ['resources/css/app.css', 'resources/app.js', 'resources/publicWishlist.js'], | ||||||
|             refresh: true, |             refresh: true, | ||||||
|         }), |         }), | ||||||
|     ], |     ], | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue