diff --git a/app/Http/Controllers/AuthController.php b/app/Http/Controllers/AuthController.php index d4ae7ea..920c336 100644 --- a/app/Http/Controllers/AuthController.php +++ b/app/Http/Controllers/AuthController.php @@ -92,6 +92,16 @@ class AuthController extends Controller 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) * diff --git a/app/Http/Controllers/WishesController.php b/app/Http/Controllers/WishesController.php index 5587251..4807846 100644 --- a/app/Http/Controllers/WishesController.php +++ b/app/Http/Controllers/WishesController.php @@ -4,6 +4,7 @@ namespace App\Http\Controllers; use Illuminate\Http\Request; use App\Models\Wish; +use App\Models\User; class WishesController extends Controller { @@ -12,6 +13,19 @@ class WishesController extends Controller 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) { $request->validate([ @@ -25,15 +39,20 @@ class WishesController extends Controller return response()->json($wish, 201); } - public function update(Request $request, Wish $wish) + public function update(Request $request) { $request->validate([ + 'id' => 'required|exists:wishes,id', + 'user_id' => 'required|exists:users,id', 'name' => 'required|string|max:256', 'price' => 'nullable|numeric', 'url' => 'nullable|url', ]); - - $wish->update($request->all()); + $wish = Wish::find($request->get('id')); + $wish->name = $request->get('name'); + $wish->price = $request->get('price'); + $wish->url = $request->get('url'); + $wish->save(); return response()->json($wish); } diff --git a/resources/PublicApp.vue b/resources/PublicApp.vue new file mode 100644 index 0000000..a20baa0 --- /dev/null +++ b/resources/PublicApp.vue @@ -0,0 +1,16 @@ + + + + + diff --git a/resources/css/app.css b/resources/css/app.css index d82198a..0dfedfd 100644 --- a/resources/css/app.css +++ b/resources/css/app.css @@ -16,3 +16,15 @@ background-color: #212022!important; color: white!important; } + +a:link { + color: aqua; +} + +a:visited { + color: darkorange; +} + +a:active { + color: crimson; +} \ No newline at end of file diff --git a/resources/js/rules.js b/resources/js/rules.js index f91263d..12d5fd1 100644 --- a/resources/js/rules.js +++ b/resources/js/rules.js @@ -5,5 +5,11 @@ export const rules = { }, notNull: 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) || 'Стоимость должна быть числом'; } } diff --git a/resources/publicWishlist.js b/resources/publicWishlist.js new file mode 100644 index 0000000..ebad752 --- /dev/null +++ b/resources/publicWishlist.js @@ -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") diff --git a/resources/store/user.js b/resources/store/user.js index 29eae75..6fa0eb2 100644 --- a/resources/store/user.js +++ b/resources/store/user.js @@ -82,6 +82,20 @@ export const useUserStore = defineStore('user', { nullifyUser() { this.setUser(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; } }, }) diff --git a/resources/store/wish.js b/resources/store/wish.js index 7d53ba6..493b4be 100644 --- a/resources/store/wish.js +++ b/resources/store/wish.js @@ -57,6 +57,39 @@ export const useWishStore = defineStore('wish', { ).then((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; + }, }, }) diff --git a/resources/views/Auth/Login.vue b/resources/views/Auth/Login.vue index adff294..d474e12 100644 --- a/resources/views/Auth/Login.vue +++ b/resources/views/Auth/Login.vue @@ -17,7 +17,8 @@ export default { rememberMe: false, errorMessage: '', errorMessageContainerStyle: '', - showPassword: false + showPassword: false, + loading: false }), methods: { validate(){ @@ -32,12 +33,14 @@ export default { } }, loginAction(){ + this.loading = true; let validation = this.validate(); if (validation !== true){ alert(validation); return; } this.userStore.login(this.email, this.password, this.rememberMe).then((isLogged) => { + this.loading = false; if (typeof isLogged == "boolean") { if (isLogged){ this.errorMessage = ''; @@ -83,7 +86,7 @@ export default { {{ errorMessage }} - Войти + Войти diff --git a/resources/views/Auth/Registration.vue b/resources/views/Auth/Registration.vue index 7cfa62c..5f382f6 100644 --- a/resources/views/Auth/Registration.vue +++ b/resources/views/Auth/Registration.vue @@ -14,7 +14,8 @@ export default { errorMessage: '', errorMessageContainerStyle: 'display: none;', showPassword: false, - showRepeatPassword: false + showRepeatPassword: false, + loading: false }), computed: { rules() { @@ -37,12 +38,14 @@ export default { return check === null ? true : check; }, registrationAction(){ + this.loading = true; let validation = this.validate(); if (validation !== true){ alert(validation); return; } this.userStore.registration(this.login, this.email, this.password, this.repeatPassword).then((isRegistred)=>{ + this.loading = false; if (typeof isRegistred == "boolean") { if (isRegistred){ this.errorMessage = ''; @@ -100,7 +103,7 @@ export default { required > {{ errorMessage }} - Регистрация + Регистрация diff --git a/resources/views/Public.vue b/resources/views/Public.vue new file mode 100644 index 0000000..48520a5 --- /dev/null +++ b/resources/views/Public.vue @@ -0,0 +1,36 @@ + + + + + + diff --git a/resources/views/PublicWishlist/ShowWhishlist.vue b/resources/views/PublicWishlist/ShowWhishlist.vue new file mode 100644 index 0000000..b5a7040 --- /dev/null +++ b/resources/views/PublicWishlist/ShowWhishlist.vue @@ -0,0 +1,54 @@ + + + + + diff --git a/resources/views/Welcome.vue b/resources/views/Welcome.vue index c197459..2d9b985 100644 --- a/resources/views/Welcome.vue +++ b/resources/views/Welcome.vue @@ -12,7 +12,8 @@ Выйти - + + @@ -26,7 +27,8 @@ export default { name: "Welcome", data: () => ({ isAuthenticated: false, - userStore: useUserStore() + userStore: useUserStore(), + fetchingUser: false }), computed: { user() { @@ -40,9 +42,11 @@ export default { } }, mounted() { + this.fetchingUser = true; this.$router.push('/auth_options'); watch(this.userStore, (newStore, oldStore)=>{ this.isAuthenticated = newStore.user !== null && newStore.user !== undefined; + this.fetchingUser = false; if (this.isAuthenticated) { this.$router.push('/wishlist'); } else { diff --git a/resources/views/Wishlist/CreateWish.vue b/resources/views/Wishlist/CreateWish.vue index 262c491..e67e0ed 100644 --- a/resources/views/Wishlist/CreateWish.vue +++ b/resources/views/Wishlist/CreateWish.vue @@ -9,7 +9,8 @@ export default { wishStore: useWishStore(), name: null, price: null, - url: null + url: null, + creating: false }), computed: { rules() { @@ -22,15 +23,33 @@ export default { }, methods: { 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(){ + this.creating = true; let validation = this.validate(); - if (typeof validation !== "boolean"){ + if (typeof validation !== "boolean"){ + this.creating = false; alert(validation); return; } this.wishStore.create(this.userStore.user['id'], this.name, this.price, this.url, this.userStore.token).then(()=>{ + this.creating = false; this.updateFrontWishes(); this.dialogCreate(); }); @@ -51,7 +70,7 @@ export default { - Создать + Создать diff --git a/resources/views/Wishlist/EditWish.vue b/resources/views/Wishlist/EditWish.vue new file mode 100644 index 0000000..1557898 --- /dev/null +++ b/resources/views/Wishlist/EditWish.vue @@ -0,0 +1,99 @@ + + + + + diff --git a/resources/views/Wishlist/Wishlist.vue b/resources/views/Wishlist/Wishlist.vue index 01191b1..503c89a 100644 --- a/resources/views/Wishlist/Wishlist.vue +++ b/resources/views/Wishlist/Wishlist.vue @@ -3,20 +3,25 @@ import {useUserStore} from "../../store/user.js"; import {useWishStore} from "../../store/wish.js"; import CreateWish from "./CreateWish.vue"; import {ref} from "vue"; +import EditWish from "./EditWish.vue"; export default { name: "Wishlist", - components: {CreateWish}, + components: {EditWish, CreateWish}, data: () => ({ userStore: useUserStore(), wishStore: useWishStore(), wishesList: [], fetching: true, dialogCreate: ref(false), - dialogEdit: ref(false) + dialogEdit: ref(false), + wishToEditId: ref(0), + wishlistLink: '', + snackbar: false }), mounted() { this.wishStore.getUserWishes(this.userStore.user['id']).then((wishes)=>{ this.wishesList = wishes; + this.wishlistLink = window.location.origin + '/wishlist/' + this.userStore.user['id']; this.fetching = false }); }, @@ -44,44 +49,64 @@ export default { }) }, editWish(id){ - + this.wishToEditId = id; + this.dialogEdit = true; }, - createWish(){ - + getWishToEditId(){ + return this.wishToEditId; + }, + copyLink(){ + navigator.clipboard.writeText(this.wishlistLink); + this.snackbar = true; } } }