Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

47 changes to the login and signup pages #18

Merged
merged 9 commits into from
Jan 5, 2022
36 changes: 30 additions & 6 deletions src/components/CreateAccountForm.vue
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,12 @@
placeholder="confirm password"
v-model="password2"
/>
<input
class="border-2 border-gray-500 w-full h-12 px-3 text-lg mt-4"
type="email"
placeholder="Email (optional)"
v-model="email"
/>
<div class="flex gap-4 flex-col mt-4">
<div>
<input class="signup-btn" type="submit" value="Signup" />
Expand All @@ -33,8 +39,10 @@
>
</div>
</div>

<div v-show="showError" class="text-red-500 mt-5 w-full">
<div v-show="!isEmailValid" class="text-red-500 mt-5 w-full">
* Please enter a valid email address
</div>
<div v-show="showError" class="text-red-500 mt-1 w-full">
*
{{ message }}
</div>
Expand All @@ -45,14 +53,15 @@
</form>
</template>
<script setup>
import { ref } from "@vue/reactivity";
import { ref, computed } from "@vue/reactivity";
import { useRouter } from "vue-router";
import userStore from "../composables/global/useStore";
const { registerUser } = userStore;
const router = useRouter();
const username = ref("");
const password = ref("");
const password2 = ref("");
const email = ref("");
const showError = ref(false);
const showSuccess = ref(false);
const message = ref("");
Expand All @@ -61,8 +70,9 @@ function register() {
setError("", false);
showError.value = false;
if (checkFormValidity() && checkPasswordsMatch()) {
registerUser(username.value, password.value)
registerUser(username.value, password.value, email.value)
.then(() => {
clearForm();
message.value = "Register successful. Redirecting to home page.";
showSuccess.value = true;
setTimeout(() => {
Expand All @@ -78,25 +88,39 @@ function setError(msg, flag) {
showError.value = flag;
}

const isEmailValid = computed(() => {
if (email.value.trim().length == 0) return true;
return /^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/.test(email.value);
});

function checkFormValidity() {
const isFormValid =
username.value?.trim().length > 0 &&
password.value?.trim().length > 0 &&
password2.value?.trim().length > 0;
password2.value?.trim().length > 0 &&
isEmailValid;

if (!isFormValid) {
setError("All fields are required", true);
setError("All fields (except email) are required", true);
}

return isFormValid;
}

function checkPasswordsMatch() {
let isMatching = password.value?.trim() === password2.value?.trim();
if (!isMatching) {
setError("Passwords should be same", true);
}
return isMatching;
}

function clearForm() {
username.value = "";
password.value = "";
password2.value = "";
email.value = "";
}
</script>
<style scoped>
.signup-btn {
Expand Down
6 changes: 6 additions & 0 deletions src/components/LoginForm.vue
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,12 @@
>Signup</router-link
>
</div>
<div>
Forgot password?
<router-link to="reset" class="text-red-500 hover:underline font-bold"
>Reset password</router-link
>
</div>
</div>

<div v-show="showError" class="text-red-500 mt-5 w-full border-red-500">
Expand Down
17 changes: 6 additions & 11 deletions src/components/Threads/ThreadList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,13 @@
</div>
</template>

<script>
<script setup>
import ThreadListItem from "./ThreadListItem.vue";

export default {
components: {
ThreadListItem,
const props = defineProps({
items: {
type: Array,
required: true,
},
props: {
items: {
type: Array,
required: true,
},
},
};
});
</script>
64 changes: 37 additions & 27 deletions src/components/Threads/ThreadListItem.vue
Original file line number Diff line number Diff line change
@@ -1,41 +1,51 @@
<template>
<router-link :to="threadLink" :class="getThreadClass(item)">
<div class="col-span-8 text-lg">{{ item.name }}</div>
<div class="col-span-2 font-semibold justify-self-end"></div>
<div class="col-span-2 font-semibold justify-self-end">
<div class="col-span-1 font-semibold justify-self-end">
<BookmarkIcon
:class="item.isFollowed ? 'fill-current text-red-500' : ''"
@click.prevent="pinThread"
class="h-5 w-5 inline-block"
/>
</div>
<div class="col-span-3 font-semibold justify-self-end">
{{ item.messageCount }}
<ChatAltIcon class="h-5 w-5 inline-block" />
</div>
</router-link>
</template>

<script>
import { ChatAltIcon } from "@heroicons/vue/outline";
<script setup>
import { ChatAltIcon, BookmarkIcon } from "@heroicons/vue/outline";
import { computed } from "vue";
import useStore from "../../composables/global/useStore";
import { useRoute } from "vue-router";

export default {
components: {
ChatAltIcon,
},
const route = useRoute();
const { followThread, getUserThreads } = useStore;

props: {
item: {
type: Object,
required: true,
},
},
methods: {
getThreadClass(item) {
var className =
"grid grid-cols-12 gap-6 p-2 text-gray-700 hover:text-red-500 hover:bg-gray-100 cursor-pointer";
if (item.id == this.$route.params.threadId) className += " text-red-500";
return className;
},
},
const threadLink = computed(
() => `/channels/${route.params.channelId}/threads/${props.item.id}`
);

computed: {
threadLink() {
return `/channels/${this.$route.params.channelId}/threads/${this.item.id}`;
},
const props = defineProps({
item: {
type: Object,
required: true,
},
};
});
function getThreadClass(item) {
var className =
"grid grid-cols-12 gap-6 p-2 text-gray-700 hover:text-red-500 hover:bg-gray-100 cursor-pointer";
if (props.item.id == route.params.threadId)
className += " text-red-500 bg-gray-100";
return className;
}

function pinThread() {
followThread({
status: !props.item.isFollowed,
threadId: props.item.id,
});
}
</script>
36 changes: 28 additions & 8 deletions src/composables/global/useStore.js
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,11 @@ async function createThread(payload) {
loadThreads(payload.topicId);
}

async function followThread(payload) {
await ThreadService.followThread(payload);
loadUserThreads();
}

async function loadChannel(id) {
return await ThreadService.getChannel(id);
}
Expand All @@ -97,6 +102,12 @@ async function loadChannels() {
}
}

async function loadUserThreads() {
if (!getLoggedInStatus.value) await registerOnce();
const userThreads = await ThreadService.getUserThreads();
setUserThreads(userThreads);
}

async function loadThreads(channelId) {
if (!getLoggedInStatus.value) await registerOnce();
const threads = await ThreadService.getThreads(channelId);
Expand All @@ -107,11 +118,6 @@ async function loadThread(threadId) {
return await ThreadService.getThread(threadId);
}

async function loadUserThreads() {
const userThreads = await ThreadService.getThreads();
setUserThreads(userThreads);
}

async function loadMessages(threadId) {
const messages = await ThreadService.getMessages(threadId);
setMessages(messages);
Expand Down Expand Up @@ -200,11 +206,21 @@ async function loginUser(username, password) {
});
}

async function registerUser(username, password) {
return await ThreadService.registerUser(username, password, {
async function forgotPassword(email) {
return await ThreadService.forgotPassword(email);
}

async function registerUser(username, password, email) {
let payload = {
username: username,
password: password,
pseudonym: getActivePseudonym.value.pseudonym,
token: getActivePseudonym.value.token,
}).then((data) => {
};
if (email.trim().length > 0) {
payload = { ...payload, email };
}
return await ThreadService.registerUser(payload).then((data) => {
updateAuthTokens(data);
});
}
Expand Down Expand Up @@ -302,9 +318,11 @@ const getId = computed(() => state.uid);
export default {
getThread,
loadThreads,
loadUserThreads,
loadThread,
loadUserThreads,
createThread,
followThread,
getUserThreads,
getThreads,

Expand Down Expand Up @@ -356,4 +374,6 @@ export default {
getActivePseudonym,

getMajorError,

forgotPassword,
};
6 changes: 6 additions & 0 deletions src/routes/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import HomePageLayout from "../layout/HomePageLayout.vue";
import LoginPage from "../views/LoginPage.vue";
import ResetPassword from "../views/ResetPassword.vue";
import CreateAccountPage from "../views/CreateAccountPage.vue";
import LandingPageLayout from "../layout/LandingPageLayout.vue";
import ThreadsPage from "../views/ThreadsPage.vue";
Expand Down Expand Up @@ -42,6 +43,11 @@ export default [
name: "home.login",
component: LoginPage,
},
{
path: "reset",
name: "home.reset",
component: ResetPassword,
},
{
path: "create-account",
name: "home.createAccount",
Expand Down
30 changes: 24 additions & 6 deletions src/service/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,14 @@ export default {
.then((x) => x.data);
},

followThread: async function (payload) {
return await axios
.post("/threads/follow", {
...payload,
})
.then((x) => x.data);
},

createMessage: async function (payload) {
return await axios
.post("/messages/", {
Expand Down Expand Up @@ -62,6 +70,10 @@ export default {
return await axios.get(`/threads/topic/${channelId}`).then((x) => x.data);
},

getUserThreads: async function (channelId) {
return await axios.get(`/threads/userthreads`).then((x) => x.data);
},

getMessages: async function (threadId) {
return await axios.get(`/messages/${threadId}`).then((x) => x.data);
},
Expand Down Expand Up @@ -99,16 +111,22 @@ export default {
.then((x) => x.data);
},

registerUser: async function (username, password, auth) {
forgotPassword: async function (email) {
return await axios
.post(`/auth/register`, {
username,
password,
...auth,
})
.post(
"/auth/forgotPassword",
{
email,
},
{ timeout: 10 * 1000 }
)
.then((x) => x.data);
},

registerUser: async function (payload) {
return await axios.post(`/auth/register`, payload).then((x) => x.data);
},

registerOnce: async function (auth) {
return await axios
.post(`/auth/register`, {
Expand Down
22 changes: 5 additions & 17 deletions src/views/CreateAccountPage.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,13 @@
<div class="lg:w-2/5">
<CreateAccountForm />
</div>
<div class="ring-red-500 ring-2 p-2 g:mt-4 lg:w-3/5 lg:self-center">
<p class="text-red-500">Need input on details for signup</p>
<p>Logged in, your pseudonyms develop <b>reputation</b>.</p>

<p>You may create up to 5 pseudonyms assocated with one account.</p>

<p>
After [1 week], your account receives the ability to downvote messages
in a thread.
</p>

<div class="ring-gray-500 ring-2 p-2 g:mt-4 lg:w-3/5 lg:self-center">
<p>Attaching an email to your account is optional.</p>
<p>
Good community behavior is rewarded, and vice versa: if your messages
repeatedly receive downvotes, suggesting the community finds them
unhelpful or inappropriate, your ability to downvote will be revoked
(until a sufficient number of upvotes are accumulated).
Adding an email enables recovery of forgotten passwords, and gives
users the option to archive inactive Threads on the interface for more
than 90 days.
</p>

<p>Please email XXX@XXX with any questions about your account.</p>
</div>
</div>
<router-link
Expand Down
Loading