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

Add functionality to create a poll. #66

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
a3a1882
Merge pull request #1 from katherineqian/nebula
katherineqian Nov 1, 2024
7732e1f
Remove unused path throwing lint error.
katherineqian Nov 1, 2024
5b7eb66
Add bg color and change text on "new space" button.
katherineqian Nov 1, 2024
5621c8c
Fix linter errors in ThreadsPage.
katherineqian Nov 1, 2024
92b426a
Move CreateThread to shared and rename to CreateSpace.
katherineqian Nov 1, 2024
6b8bcde
Remove standard body padding on Modal (prevents desired layout for Cr…
katherineqian Nov 1, 2024
9d35fd8
Rename Modal -> ThemedModal for lint error requiring multi-word templ…
katherineqian Nov 1, 2024
edde54a
Remove unnecessary `const props` usage.
katherineqian Nov 1, 2024
c8d19b4
Add some minor top padding to CreateChannel option buttons.
katherineqian Nov 1, 2024
1a36ac7
Fix lint error on CreateChannel.vue (unnecessary backslash in regex).
katherineqian Nov 1, 2024
5f1685f
Add working tabs to CreateSpace dialog.
katherineqian Nov 1, 2024
e06a54a
Add description and padding to New Thread dialog.
katherineqian Nov 1, 2024
9a3edfc
Change icon for Threshold Poll.
katherineqian Nov 1, 2024
b8d413b
Factor out Create Thread form to a new component called CreateThread,…
katherineqian Nov 1, 2024
9347814
Set up CreatePoll file for Create Poll tab content.
katherineqian Nov 1, 2024
250cd99
Implement working CreatePoll page with title input only.
katherineqian Nov 1, 2024
d3c8e05
Remove unused variables and addChannel function in useStore.js throwi…
katherineqian Nov 1, 2024
8ac4e5a
Implement undefined setMajorError function in useStore.js.
katherineqian Nov 1, 2024
e4fc306
Create new PollService and use it in useStore.js.
katherineqian Nov 1, 2024
58f1621
Rename pollTitle to title; change validation to individual functions …
katherineqian Nov 1, 2024
2954dd0
Add a description field. Remove login-form-field from inputs.
katherineqian Nov 1, 2024
3febefb
Implement basic HTML date picker for end date.
katherineqian Nov 2, 2024
82f0b82
Set dynamic default values for date picker (default to expire 5 days …
katherineqian Nov 2, 2024
8a730b9
Remove unused props.
katherineqian Nov 2, 2024
cd02c37
Convert expiration date to value and pass into poll creation.
katherineqian Nov 2, 2024
79797d9
Update create call input parameters based on Brendan's API changes.
katherineqian Nov 8, 2024
d60ef67
Tie createSucess to closeModal on CreatePoll.
katherineqian Nov 8, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions src/components/Banner/BannerSection.vue
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@
</div>
</div>

<!-- <Modal :is-open="isModalOpen" @close-modal="closeModal">
<!-- <ThemedModal :is-open="isModalOpen" @close-modal="closeModal">
<template v-slot:title>Delete Pseudonym</template>
<div class="text-xl">Are you sure you want to delete pseudonym?</div>
<div class="mt-3 text-lg">
Expand Down Expand Up @@ -114,7 +114,7 @@
Delete
</button>
</template>
</Modal> -->
</ThemedModal> -->
</div>
</template>

Expand All @@ -123,7 +123,7 @@ import { onMounted, watch, ref, computed, nextTick } from 'vue'
import useStore from '../../composables/global/useStore'
import { defineAsyncComponent } from '@vue/runtime-core'
import { TrashIcon, RefreshIcon, LoginIcon, DotsVerticalIcon } from '@heroicons/vue/outline'
import Modal from '../Shared/Modal.vue'
import ThemedModal from '../Shared/ThemedModal.vue'
import { useRoute } from 'vue-router'

const {
Expand Down
10 changes: 5 additions & 5 deletions src/components/Channels/CreateChannel.vue
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
<option value="public">Public</option>
<option value="private">Private</option>
</select>
<Modal :is-open="isModalOpen" @close-modal="closeModal">
<ThemedModal :is-open="isModalOpen" @close-modal="closeModal">
<template #title>Create {{ channelTypeName }} Channel</template>
<span class="font-semibold">Channel name:</span>
<div>
Expand All @@ -20,7 +20,7 @@
placeholder="Enter channel name"
/>
</div>
<div class="mt-2">
<div class="mt-4">
<input
id="disableVoting"
v-model="disableVoting"
Expand Down Expand Up @@ -68,13 +68,13 @@
Create
</button>
</template>
</Modal>
</ThemedModal>
</template>

<script setup>
import { computed, ref } from '@vue/reactivity'
import useStore from '../../composables/global/useStore'
import Modal from '../Shared/Modal.vue'
import ThemedModal from '../Shared/ThemedModal.vue'
const { getLoggedInStatus, createChannel, getGuestStatus, loadUser } = useStore

const isModalOpen = ref(false)
Expand All @@ -89,7 +89,7 @@ const channelTypeName = computed(() => channelType.value[0].toUpperCase() + chan

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

function closeModal() {
Expand Down
6 changes: 3 additions & 3 deletions src/components/Channels/DeleteChannel.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<TrashIcon class="h-4 w-4" />
<span class="sr-only">Delete</span>
</button>
<Modal :is-open="isModalOpen" @close-modal="closeModal">
<ThemedModal :is-open="isModalOpen" @close-modal="closeModal">
<template #title>Delete Channel</template>
<div>
Are you sure you want to delete
Expand All @@ -24,13 +24,13 @@
Delete
</button>
</template>
</Modal>
</ThemedModal>
</template>

<script setup>
import { TrashIcon } from '@heroicons/vue/outline'
import { ref } from '@vue/reactivity'
import Modal from '../Shared/Modal.vue'
import ThemedModal from '../Shared/ThemedModal.vue'

defineProps({
show: {
Expand Down
6 changes: 3 additions & 3 deletions src/components/Channels/EditChannel.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<PencilIcon class="h-4 w-4" />
<span class="sr-only">Edit</span>
</button>
<Modal :is-open="isModalOpen" @close-modal="closeModal">
<ThemedModal :is-open="isModalOpen" @close-modal="closeModal">
<template #title>Edit Channel</template>
<span class="font-semibold">Channel name:</span>
<div>
Expand Down Expand Up @@ -60,14 +60,14 @@
Update
</button>
</template>
</Modal>
</ThemedModal>
</template>

<script setup>
import { PencilIcon } from '@heroicons/vue/outline'
import { computed, ref } from '@vue/reactivity'
import useStore from '../../composables/global/useStore'
import Modal from '../Shared/Modal.vue'
import ThemedModal from '../Shared/ThemedModal.vue'
const { updateChannel, getGuestStatus } = useStore

const isModalOpen = ref(false)
Expand Down
6 changes: 3 additions & 3 deletions src/components/Messages/PromptDirtyDraft.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<template>
<Modal :is-open="isModalOpen" @close-modal="closeModal">
<ThemedModal :is-open="isModalOpen" @close-modal="closeModal">
<template #title>Draft will be lost.</template>
<div class="font-semibold">
<p>Are you sure you want to leave?</p>
Expand All @@ -19,14 +19,14 @@
Yes
</button>
</template>
</Modal>
</ThemedModal>
</template>

<script setup>
import { TrashIcon } from '@heroicons/vue/outline'
import { ref } from '@vue/reactivity'
import { watch } from 'vue'
import Modal from '../Shared/Modal.vue'
import ThemedModal from '../Shared/ThemedModal.vue'

const props = defineProps({
show: {
Expand Down
74 changes: 74 additions & 0 deletions src/components/Polls/CreatePoll.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
<template>
<p class="text-gray-600 mb-4">
katherineqian marked this conversation as resolved.
Show resolved Hide resolved
Submit responses and vote on them anonymously. When a response gets enough votes, voters for that response reveal their
names.
</p>
<div class="mb-4">
<span class="font-semibold">Poll title:</span>
<div>
<input v-model="title" class="border rounded border-gray-500 w-full h-12 px-3" type="text" />
</div>
</div>
<div class="mb-4">
<span class="font-semibold">Description:</span>
<div>
<textarea v-model="description" rows="2" class="h-full border rounded border-gray-500 w-full p-3" type="text">
</textarea>
</div>
</div>
<div class="mb-4">
<p class="font-semibold">End date:</p>

<!-- Date picker -->
<div class="flex max-w-sm border rounded border-gray-500 w-full">
<input v-model="expirationDate" class="rounded w-full p-3" type="date" :min="today" />
katherineqian marked this conversation as resolved.
Show resolved Hide resolved
</div>
</div>
<!-- Error message -->
<div class="text-harvard-red mt-2">{{ message }}</div>
</template>

<script setup>
import { ref } from '@vue/reactivity'
import useStore from '../../composables/global/useStore'
import { useRoute } from 'vue-router'

const { createPoll } = useStore
const title = ref('')
const description = ref('')
const message = ref('')
const route = useRoute()

const today = new Date().toISOString().split('T')[0]
const date = new Date()
date.setDate(date.getDate() + 5)
const defaultDate = date.toISOString().split('T')[0]

const expirationDate = ref(defaultDate)

defineExpose({
processCreate
})

const emit = defineEmits(['createSuccess'])

function processCreate() {
if (!hasTitle()) {
message.value = 'A title is required.'
return
}
const expirationDateValue = new Date(expirationDate.value)
createPoll({
title: title.value,
description: description.value,
katherineqian marked this conversation as resolved.
Show resolved Hide resolved
expirationDate: expirationDateValue,
topicId: route.params.channelId
})
.then((x) => emit('createSuccess'))
.catch((err) => (message.value = err.response.data.message))
}

function hasTitle() {
return title.value.trim().length > 0
}
</script>
100 changes: 100 additions & 0 deletions src/components/Shared/CreateSpace.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
<template>
<button
v-if="show"
class="flex gap-2 justify-start items-center bg-harvard-red text-white p-2 rounded-md shadow-md"
@click="openModal"
>
<PlusCircleIcon class="w-5 h-5" /> new space
</button>
<ThemedModal :is-open="isModalOpen" @close-modal="closeModal">
<template #title>New space</template>
<!-- Space type tabs -->
<ul class="flex flex-wrap text-center text-gray-500 border-b border-gray-200">
<li>
<button
class="flex gap-1 px-4 py-2 rounded-t-lg"
:class="tab === 1 ? 'text-harvard-red bg-gray-100 font-bold' : ''"
@click="openTab(1)"
>
<HashtagIcon class="w-5 h-5" />
Thread
</button>
</li>
<li>
<button
class="flex gap-1 px-4 py-2 rounded-t-lg"
:class="tab === 2 ? 'text-harvard-red bg-gray-100 font-bold' : ''"
@click="openTab(2)"
>
<UserGroupIcon class="w-5 h-5" />
Threshold Poll
</button>
</li>
</ul>
<!-- Tab content -->
<div v-show="tab === 1" class="py-3 mb-5">
<CreateThread ref="createThreadRef" @create-success="closeModal" />
</div>
<div v-show="tab === 2" class="py-3 mb-5">
<CreatePoll ref="createPollRef" @create-success="closeModal" />
</div>
<!-- Action buttons -->
<template #actions>
<button
class="rounded bg-gray-300 px-2 py-2 font-semibold shadow-sm hover:bg-gray-400 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-gray-600"
@click="closeModal"
>
Cancel
</button>
<button
class="rounded bg-gray-600 px-2 py-2 font-semibold text-white shadow-sm hover:bg-gray-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-gray-600"
@click="onSubmit"
>
Create
</button>
</template>
</ThemedModal>
</template>

<script setup>
import { ref } from '@vue/reactivity'
import ThemedModal from './ThemedModal.vue'
import CreateThread from '../Threads/CreateThread.vue'
import CreatePoll from '../Polls/CreatePoll.vue'
import { PlusCircleIcon, HashtagIcon, UserGroupIcon } from '@heroicons/vue/outline'

defineProps({
show: {
type: Boolean,
required: true
}
})

const isModalOpen = ref(false)
const tab = ref(1)
const createThreadRef = ref(null)
const createPollRef = ref(null)

function closeModal() {
document.querySelector('body').classList.remove('modal-open')
isModalOpen.value = false
}

function openModal() {
window.scrollTo({ top: 0, left: 0 })
isModalOpen.value = true
document.querySelector('body').classList.add('modal-open')
}

function openTab(tabNumber) {
tab.value = tabNumber
}

function onSubmit() {
if (tab.value === 1) {
createThreadRef.value.processCreate()
} else if (tab.value === 2) {
createPollRef.value.processCreate()
}
}
</script>
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<slot name="title">Modal Title</slot>
<XIcon class="mt-1 float-right h-6 w-6 inline-block cursor-pointer" title="Close" @click="closeModal" />
</div>
<div class="flex-grow py-3"><slot>Modal Body</slot></div>
<div class="flex-grow"><slot>Modal Body</slot></div>
<div class="flex justify-end my-3 gap-4">
<slot name="actions"><button @click="closeModal"></button></slot>
</div>
Expand All @@ -18,7 +18,7 @@
<script setup>
import { XIcon } from '@heroicons/vue/outline'

const props = defineProps({
defineProps({
isOpen: {
type: Boolean,
required: true
Expand Down
Loading