improved registration page and added account page

This commit is contained in:
2026-01-03 14:22:21 +01:00
parent d96cc39a65
commit f3a2c98643
11 changed files with 166 additions and 60 deletions

2
src-tauri/Cargo.lock generated
View File

@@ -437,7 +437,7 @@ checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724"
[[package]]
name = "chatapp"
version = "0.1.0"
version = "1.0.0"
dependencies = [
"serde",
"serde_json",

View File

@@ -1,3 +1,28 @@
<template>
<div class="backdrop" @click.self="emit('close')">
<form class="modal" @submit.prevent="submit">
<h2>Create room</h2>
<input v-model="name" placeholder="Room name" autofocus />
<label class="checkbox">
<input type="checkbox" v-model="global" />
<span>Global room</span>
</label>
<div class="actions">
<button type="button" @click="emit('close')" class="secondary">
Cancel
</button>
<button type="submit">
Create
</button>
</div>
</form>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import { createRoom } from '../api/rooms'
@@ -20,26 +45,6 @@ async function submit() {
}
</script>
<template>
<div class="backdrop" @click.self="emit('close')">
<div class="modal">
<h2>Create room</h2>
<input v-model="name" placeholder="Room name" />
<label class="checkbox">
<input type="checkbox" v-model="global" />
<span>Global room</span>
</label>
<div class="actions">
<button @click="emit('close')" class="secondary">Cancel</button>
<button @click="submit">Create</button>
</div>
</div>
</div>
</template>
<style scoped>
.backdrop {
position: fixed;

View File

@@ -1,11 +1,11 @@
<template>
<div class="backdrop" @click.self="emit('close')">
<div class="modal">
<form class="modal" @submit.prevent="submit">
<h2>Invite People</h2>
<p v-if="errorMessage" class="error-message">{{ errorMessage }}</p>
<input v-model="receiverUsername" placeholder="username" />
<input v-model="receiverUsername" placeholder="username" autofocus />
<label class="checkbox">
<input type="checkbox" v-model="requestFriend" />
@@ -13,10 +13,15 @@
</label>
<div class="actions">
<button @click="emit('close')" class="secondary">Cancel</button>
<button @click="submit">Send</button>
<button type="button" @click="emit('close')" class="secondary">
Cancel
</button>
<button type="submit">
Send
</button>
</div>
</div>
</form>
</div>
</template>

View File

@@ -14,27 +14,19 @@
<span v-if="totalCount > 0" class="badge">{{ totalCount }}</span>
</router-link>
<button class="nav-item logout" @click="logout">
<i class="fa-solid fa-right-from-bracket"></i>
</button>
<router-link to="/account" class="nav-item">
<i class="fa-solid fa-circle-user"></i>
</router-link>
</nav>
</div>
</template>
<script setup lang="ts">
import { useRouter } from 'vue-router'
import { onMounted } from 'vue'
import { logout as authLogout } from '../store.ts'
import { useNotifications } from '../store'
const router = useRouter()
const { totalCount, refreshNotifications } = useNotifications()
function logout() {
authLogout()
router.push('/login')
}
onMounted(() => {
refreshNotifications()
})
@@ -106,20 +98,12 @@ onMounted(() => {
.nav-item:not(.router-link-active):hover i {
color: var(--text);
}
.nav-item.logout:hover i {
color: rgba(255, 80, 80, 0.8);
}
}
.router-link-active i {
color: var(--accent);
}
.nav-item.logout:hover i {
color: rgba(255, 80, 80, 0.8);
}
@media (max-width: 720px) {
#bottom-nav {
bottom: 16px;

View File

@@ -15,7 +15,7 @@ async function init() {
init()
// export const API = 'http://127.0.0.1:8080'
export const API = 'https://alatreon.org/chatapp'
// export const API_WS = 'ws://127.0.0.1:8080/ws'
export const API_WS = 'wss://alatreon.org/chatapp/ws'
export const API = 'http://127.0.0.1:8080'
// export const API = 'https://alatreon.org/chatapp'
export const API_WS = 'ws://127.0.0.1:8080/ws'
// export const API_WS = 'wss://alatreon.org/chatapp/ws'

87
src/pages/AccountPage.vue Normal file
View File

@@ -0,0 +1,87 @@
<template>
<div class="account-page">
<h1>Your Account</h1>
<div v-if="user" class="info-card">
<p><strong>Username:</strong> {{ user.username }}</p>
<p><strong>Email:</strong> {{ user.email }}</p>
</div>
<div v-else>
<p>Loading account details...</p>
</div>
<button class="logout-btn" @click="logout">
<i class="fa-solid fa-right-from-bracket"></i>
<span>Logout</span>
</button>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted } from 'vue'
import { useRouter } from 'vue-router'
import { logout as authLogout } from '../store.ts'
import { getAuthData } from "../authStore.ts"
import type { User } from "../types"
const router = useRouter()
const user = ref<User | null>(null)
onMounted(async () => {
try {
const auth = await getAuthData()
user.value = auth.user
} catch (err) {
console.error("Failed to load user data:", err)
}
})
function logout() {
authLogout()
router.push('/login')
}
</script>
<style scoped>
.account-page {
max-width: 720px;
margin: 0 auto;
padding: 2rem 1.5rem;
display: flex;
flex-direction: column;
gap: 2rem;
}
.info-card {
background: var(--panel);
border: 1px solid var(--border);
border-radius: var(--radius);
padding: 1rem;
}
.logout-btn {
cursor: pointer;
display: flex;
align-items: center;
gap: 10px;
padding: 10px 20px;
color: var(--text);
background-color: transparent;
border: 1px solid #ff5050;
border-radius: 8px;
width: fit-content;
transition: all 0.2s ease;
}
.logout-btn:hover {
color: rgba(255, 80, 80, 0.8);
}
.logout-btn:hover i {
color: rgba(255, 80, 80, 0.8);
}
.logout-btn i {
font-size: 1.25rem;
}
</style>

View File

@@ -3,15 +3,14 @@
<header class="friends-header">
<h1>Your friends</h1>
<!-- Friend Request Form -->
<div class="friend-request-form">
<form class="friend-request-form" @submit.prevent="send">
<h3>Add Friend</h3>
<div class="input-container">
<input v-model="username" placeholder="Username" />
<button @click="send">Send Request</button>
<input v-model="username" placeholder="Username" autofocus />
<button type="submit">Send Request</button>
</div>
<p v-if="errorMessage" class="error-message">{{ errorMessage }}</p>
</div>
</form>
</header>
<!-- Friends List -->
@@ -49,6 +48,7 @@ async function send() {
await sendFriendRequest(username.value)
username.value = ''
errorMessage.value = ''
friends.value = await fetchFriends()
} catch (err: any) {
errorMessage.value = err
}

View File

@@ -1,11 +1,12 @@
<template>
<div class="login-page">
<form class="login-card" @submit.prevent="submit">
<form class="login-card" @submit.prevent="submit" novalidate>
<h1>Register</h1>
<input v-model="email" type="email" placeholder="email" required />
<input v-model="username" placeholder="username" required />
<input v-model="password" type="password" placeholder="password" required />
<input v-model="confirmPassword" type="password" placeholder="confirm password" required />
<button type="submit">Create Account</button>
@@ -26,15 +27,34 @@ import { useRouter } from "vue-router";
const email = ref("");
const username = ref("");
const password = ref("");
const confirmPassword = ref("");
const errorMessage = ref("");
const router = useRouter();
async function submit() {
async function submit(event: Event) {
errorMessage.value = "";
const form = event.target as HTMLFormElement;
// Check password length and email
if (!form.checkValidity()) {
if (password.value.length < 8) {
errorMessage.value = "Password must be at least 8 characters long";
} else {
errorMessage.value = "Please enter a valid email address";
}
return;
}
// Check password match
if (password.value !== confirmPassword.value) {
errorMessage.value = "Passwords do not match";
return;
}
try {
await register(email.value, username.value, password.value);
router.push("/");
} catch (err: any) {
errorMessage.value = err?.message || "An unknown error occurred";
@@ -75,7 +95,6 @@ async function submit() {
margin-top: 0.5rem;
}
.login-link {
font-size: 0.9rem;
text-align: center;

View File

@@ -6,6 +6,7 @@ import RegisterPage from './pages/RegisterPage.vue'
import ChatPage from './pages/ChatPage.vue'
import FriendListPage from './pages/FriendListPage.vue'
import NofificationsPage from './pages/NotificationsPage.vue'
import AccountPage from './pages/AccountPage.vue'
const router = createRouter({
history: createWebHistory(),
@@ -30,7 +31,8 @@ const router = createRouter({
props: true
},
{ path: '/friendlist', component: FriendListPage },
{ path: '/notifications', component: NofificationsPage }
{ path: '/notifications', component: NofificationsPage },
{ path: '/account', component: AccountPage }
],
})

View File

@@ -18,7 +18,8 @@ export async function login(email: string, username: string, password: string) {
let user: User = {
uuid: res.uuid,
username: username
username: res.username,
email: res.email
};
await authStore.saveAuthData(res.token, user)
return { token: res.token, uuid: res.uuid, isAuthenticated: true }

View File

@@ -1,10 +1,13 @@
export interface User {
uuid: string
username: string
email: string
}
export interface LoginResponse {
uuid: string
username: string
email: string
token: string
}