Convert frontend to Vue #3
| @@ -98,27 +98,37 @@ func (h *Handler) loginPost(c *gin.Context) { | |||||||
| 	}) | 	}) | ||||||
| } | } | ||||||
|  |  | ||||||
| func (h *Handler) registerPost(c *gin.Context) { | type registerInformation struct { | ||||||
| 	email, _ := c.GetPostForm("email") | 	Password string `json:"password"` | ||||||
| 	password, _ := c.GetPostForm("password") | 	Email    string `json:"email"` | ||||||
| 	name, _ := c.GetPostForm("name") | 	Name     string `json:"name"` | ||||||
|  | } | ||||||
|  |  | ||||||
| 	_, err := h.Service.GetUserByUsername(c.Request.Context(), email) | func (h *Handler) registerPost(c *gin.Context) { | ||||||
| 	if err == nil { | 	var register registerInformation | ||||||
| 		c.AbortWithStatus(http.StatusUnauthorized) | 	c.BindJSON(®ister) | ||||||
|  |  | ||||||
|  | 	if register.Email == "" || register.Password == "" || register.Name == "" { | ||||||
|  | 		c.AbortWithError(http.StatusBadRequest, fmt.Errorf("e-mail, password and name are required")) | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	hash, err := h.CredentialsVerifier.Hash(password) | 	_, err := h.Service.GetUserByUsername(c.Request.Context(), register.Email) | ||||||
|  | 	if err == nil { | ||||||
|  | 		c.AbortWithError(http.StatusUnauthorized, err) | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	hash, err := h.CredentialsVerifier.Hash(register.Password) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		c.AbortWithError(http.StatusUnauthorized, err) | 		c.AbortWithError(http.StatusUnauthorized, err) | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	createUser := postgres.CreateUserParams{ | 	createUser := postgres.CreateUserParams{ | ||||||
| 		Name:     name, | 		Name:     register.Name, | ||||||
| 		Password: hash, | 		Password: hash, | ||||||
| 		Email:    email, | 		Email:    register.Email, | ||||||
| 	} | 	} | ||||||
| 	_, err = h.Service.CreateUser(c.Request.Context(), createUser) | 	_, err = h.Service.CreateUser(c.Request.Context(), createUser) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
|   | |||||||
| @@ -19,13 +19,19 @@ export default { | |||||||
| </script> | </script> | ||||||
|  |  | ||||||
| <template> | <template> | ||||||
|  |   <v-app> | ||||||
|  |     <v-app-bar app> | ||||||
|       <ul> |       <ul> | ||||||
|         <li v-if="!loggedIn"><router-link to="/login">Login</router-link></li> |         <li v-if="!loggedIn"><router-link to="/login">Login</router-link></li> | ||||||
|         <li v-if="loggedIn"><a @click="logout">Logout</a></li> |         <li v-if="loggedIn"><a @click="logout">Logout</a></li> | ||||||
|         <li v-if="loggedIn"><router-link to="/">Dashboard</router-link></li> |         <li v-if="loggedIn"><router-link to="/">Dashboard</router-link></li> | ||||||
|       </ul> |       </ul> | ||||||
|  |     </v-app-bar> | ||||||
|    |    | ||||||
|  |     <v-main> | ||||||
|       <router-view></router-view> |       <router-view></router-view> | ||||||
|  |     </v-main> | ||||||
|  |   </v-app> | ||||||
| </template> | </template> | ||||||
|  |  | ||||||
| <style> | <style> | ||||||
|   | |||||||
| @@ -2,8 +2,13 @@ import { createApp } from 'vue/dist/vue.esm-bundler' | |||||||
| import App from './App.vue' | import App from './App.vue' | ||||||
| import router from './router/routes.js' | import router from './router/routes.js' | ||||||
| import store from './store/index.js' | import store from './store/index.js' | ||||||
|  | import vuetify from './plugins/vuetify' | ||||||
|  | import { loadFonts } from './plugins/webfontloader' | ||||||
|  |  | ||||||
|  | loadFonts() | ||||||
|  |  | ||||||
| const app = createApp(App) | const app = createApp(App) | ||||||
| app.use(router) | app.use(router) | ||||||
| app.use(store) | app.use(store) | ||||||
|  | app.use(vuetify) | ||||||
| app.mount('#app') | app.mount('#app') | ||||||
|   | |||||||
| @@ -7,11 +7,12 @@ export default { | |||||||
|     }, |     }, | ||||||
|     data() { |     data() { | ||||||
|         return { |         return { | ||||||
|             error: false, |             error: [], | ||||||
|             login: { |             login: { | ||||||
|                 user: "",  |                 user: "",  | ||||||
|                 password: "" |                 password: "" | ||||||
|             } |             }, | ||||||
|  |             showPassword: false | ||||||
|         } |         } | ||||||
|     }, |     }, | ||||||
|     mounted () { |     mounted () { | ||||||
| @@ -20,14 +21,13 @@ export default { | |||||||
|     methods: { |     methods: { | ||||||
|         formSubmit (e) { |         formSubmit (e) { | ||||||
|             e.preventDefault(); |             e.preventDefault(); | ||||||
|             console.log("uiae"); |  | ||||||
|             fetch("/api/v1/user/login", {method: "POST", body: JSON.stringify(this.$data.login)}) |             fetch("/api/v1/user/login", {method: "POST", body: JSON.stringify(this.$data.login)}) | ||||||
|                 .then(x => x.json()) |                 .then(x => x.json()) | ||||||
|                 .then(x => { |                 .then(x => { | ||||||
|                     this.$data.error = "" |                     this.$data.error = "" | ||||||
|                     this.$store.commit("setToken", x.token); |                     this.$store.commit("setToken", x.token); | ||||||
|                 }) |                 }) | ||||||
|                 .catch(x => this.$data.error = "Error"); |                 .catch(x => this.$data.error = ["The entered credentials are invalid!"]); | ||||||
|  |  | ||||||
|             // TODO display invalidCredentials |             // TODO display invalidCredentials | ||||||
|             // TODO redirect to dashboard on success |             // TODO redirect to dashboard on success | ||||||
| @@ -37,24 +37,27 @@ export default { | |||||||
| </script> | </script> | ||||||
|  |  | ||||||
| <template> | <template> | ||||||
| <form id="loginForm" @submit="formSubmit" class="center-block"> |     <v-container> | ||||||
|  |         <v-row> | ||||||
|  |             <v-col cols="12"> | ||||||
|  |                 <v-text-field v-model="login.user" type="text" label="Username" /> | ||||||
|  |             </v-col> | ||||||
|  |             <v-col cols="12"> | ||||||
|  |                 <v-text-field v-model="login.password" label="Password" | ||||||
|  |                     :append-icon="showPassword ? 'mdi-eye' : 'mdi-eye-off'"  | ||||||
|  |                     :type="showPassword ? 'text' : 'password'" | ||||||
|  |                     @click:append="showPassword = showPassword" | ||||||
|  |                     :error-message="error" | ||||||
|  |                     error-count="2" | ||||||
|  |                     error /> | ||||||
|  |             </v-col> | ||||||
|  |         </v-row> | ||||||
|         <div class="form-group"> |         <div class="form-group"> | ||||||
| 		<label for="username">User</label> |             {{ error }} | ||||||
| 		<input type="text" class="form-control" placeholder="User" v-model="login.user" /> |  | ||||||
|         </div> |         </div> | ||||||
|  |         <v-btn type="submit" @click="formSubmit">Login</v-btn> | ||||||
| 	<div class="form-group"> |  | ||||||
| 		<label for="password">Password</label> |  | ||||||
| 		<input type="password" class="form-control" placeholder="Password" v-model="login.password" /> |  | ||||||
| 		<p v-if="error"> |  | ||||||
| 			The entered credentials are invalid |  | ||||||
| 		</p> |  | ||||||
| 	</div> |  | ||||||
|  |  | ||||||
| 	<input type="submit" value="Login" class="btn btn-default" on/> |  | ||||||
|  |  | ||||||
|         <p> |         <p> | ||||||
| 		New user? <a href="/register">Register</a> instead! | 	        New user? <router-link to="/register">Register</router-link> instead! | ||||||
|         </p> |         </p> | ||||||
| </form> |     </v-container> | ||||||
| </template> | </template> | ||||||
							
								
								
									
										126
									
								
								web/src/pages/Register.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										126
									
								
								web/src/pages/Register.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,126 @@ | |||||||
|  | <!--{{define "title"}}Register{{end}} | ||||||
|  |  | ||||||
|  | {{template "base" .}} | ||||||
|  |  | ||||||
|  | {{define "more-head"}} | ||||||
|  | <script> | ||||||
|  | function checkPasswordMatchUi() { | ||||||
|  |     if(checkPasswordMatch()) | ||||||
|  |         $("#divCheckPasswordMatch").html("Passwords match."); | ||||||
|  |     else | ||||||
|  |         $("#divCheckPasswordMatch").html("Passwords do not match!"); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function checkPasswordMatch() { | ||||||
|  |     var password = $("#password").val(); | ||||||
|  |     var confirmPassword = $("#password_confirm").val(); | ||||||
|  |     return password == confirmPassword; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | $(document).ready(function () { | ||||||
|  |     $("#password, #password_confirm").keyup(checkPasswordMatchUi); | ||||||
|  |     $('#invalidCredentials').hide();  | ||||||
|  |     $('#loginForm').ajaxForm({ | ||||||
|  |         beforeSubmit: function(a, b, c) { | ||||||
|  |             var match = checkPasswordMatch(); | ||||||
|  |             if(!match){ | ||||||
|  |                 $("#divCheckPasswordMatch").fadeOut(300).fadeIn(300).fadeOut(300).fadeIn(300); | ||||||
|  |             } | ||||||
|  |             return match; | ||||||
|  |         }, | ||||||
|  |         success: function() { | ||||||
|  |             window.location.href = "/dashboard"; | ||||||
|  |         }, | ||||||
|  |         error: function() { | ||||||
|  |             $('#invalidCredentials').show(); | ||||||
|  |         } | ||||||
|  |     });  | ||||||
|  | });  | ||||||
|  | </script>  | ||||||
|  | {{end}} | ||||||
|  |  | ||||||
|  | {{define "main"}} | ||||||
|  | <form id="loginForm" action="/api/v1/user/register" method="POST" class="center-block"> | ||||||
|  |     <div class="form-group"> | ||||||
|  |         <label for="password">Password</label> | ||||||
|  |         <input type="password" name="password" id="password" class="form-control" placeholder="Password" /> | ||||||
|  |         <input type="password" id="password_confirm" class="form-control" placeholder="Verify password" /> | ||||||
|  |     </div> | ||||||
|  |      | ||||||
|  |     <div id="divCheckPasswordMatch"></div> | ||||||
|  |  | ||||||
|  |     <div id="invalidCredentials"> | ||||||
|  |         Username already exists | ||||||
|  |     </div> | ||||||
|  |  | ||||||
|  |     <input type="submit" value="Login" class="form-control" /> | ||||||
|  |  | ||||||
|  | </form> | ||||||
|  | {{end}}--> | ||||||
|  |  | ||||||
|  | <script> | ||||||
|  | export default { | ||||||
|  |     data() { | ||||||
|  |         return { | ||||||
|  |             login: { | ||||||
|  |                 email: "", | ||||||
|  |                 password: "", | ||||||
|  |                 name: "" | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     }, | ||||||
|  |     methods: { | ||||||
|  |         formSubmit (e) { | ||||||
|  |             e.preventDefault(); | ||||||
|  |             fetch("/api/v1/user/register", {method: "POST", body: JSON.stringify(this.$data.login)}) | ||||||
|  |                 .then(x => x.json()) | ||||||
|  |                 .then(x => { | ||||||
|  |                     this.$data.error = "" | ||||||
|  |                     this.$store.commit("setToken", x.token); | ||||||
|  |                 }) | ||||||
|  |                 .catch(x => this.$data.error = ["Something went wrong!"]); | ||||||
|  |  | ||||||
|  |             // TODO display invalidCredentials | ||||||
|  |             // TODO redirect to dashboard on success | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | </script> | ||||||
|  |  | ||||||
|  | <template> | ||||||
|  |     <v-container> | ||||||
|  |         <v-row> | ||||||
|  |             <v-col cols="12"> | ||||||
|  |                 <v-text-field v-model="login.email" type="text" label="E-Mail" /> | ||||||
|  |             </v-col> | ||||||
|  |             <v-col cols="12"> | ||||||
|  |                 <v-text-field v-model="login.name" type="text" label="Name" /> | ||||||
|  |             </v-col> | ||||||
|  |             <v-col cols="6"> | ||||||
|  |                 <v-text-field v-model="login.password" label="Password" | ||||||
|  |                     :append-icon="showPassword ? 'mdi-eye' : 'mdi-eye-off'"  | ||||||
|  |                     :type="showPassword ? 'text' : 'password'" | ||||||
|  |                     @click:append="showPassword = showPassword" | ||||||
|  |                     :error-message="error" | ||||||
|  |                     error-count="2" | ||||||
|  |                     error /> | ||||||
|  |             </v-col> | ||||||
|  |             <v-col cols="6"> | ||||||
|  |                 <v-text-field v-model="login.password" label="Repeat password" | ||||||
|  |                     :append-icon="showPassword ? 'mdi-eye' : 'mdi-eye-off'"  | ||||||
|  |                     :type="showPassword ? 'text' : 'password'" | ||||||
|  |                     @click:append="showPassword = showPassword" | ||||||
|  |                     :error-message="error" | ||||||
|  |                     error-count="2" | ||||||
|  |                     error /> | ||||||
|  |             </v-col> | ||||||
|  |         </v-row> | ||||||
|  |         <div class="form-group"> | ||||||
|  |             {{ error }} | ||||||
|  |         </div> | ||||||
|  |         <v-btn type="submit" @click="formSubmit">Register</v-btn> | ||||||
|  | 	    <p> | ||||||
|  | 		    Existing user? <router-link to="/login">Login</router-link> instead! | ||||||
|  |     	</p> | ||||||
|  |     </v-container> | ||||||
|  | </template> | ||||||
| @@ -2,10 +2,12 @@ import { createRouter, createWebHashHistory } from 'vue-router' | |||||||
| import Budget from '../pages/Budget.vue'; | import Budget from '../pages/Budget.vue'; | ||||||
| import Dashboard from '../pages/Dashboard.vue'; | import Dashboard from '../pages/Dashboard.vue'; | ||||||
| import Login from '../pages/Login.vue'; | import Login from '../pages/Login.vue'; | ||||||
|  | import Register from '../pages/Register.vue'; | ||||||
|  |  | ||||||
| const routes = [ | const routes = [ | ||||||
|   { path: '/', name: 'Index', component: Dashboard }, |   { path: '/', name: 'Index', component: Dashboard }, | ||||||
|   { path: '/login', name: 'Login', component: Login }, |   { path: '/login', name: 'Login', component: Login }, | ||||||
|  |   { path: '/register', name: 'Register', component: Register }, | ||||||
|   { path: '/budget/:budgetid',  name: 'Budget', component: Budget }, |   { path: '/budget/:budgetid',  name: 'Budget', component: Budget }, | ||||||
| ] | ] | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										5652
									
								
								web/yarn.lock
									
									
									
									
									
								
							
							
						
						
									
										5652
									
								
								web/yarn.lock
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
		Reference in New Issue
	
	Block a user