diff --git a/packages/app/src/components/Poll/index.jsx b/packages/app/src/components/Poll/index.jsx
index 0da84d84..df32e245 100644
--- a/packages/app/src/components/Poll/index.jsx
+++ b/packages/app/src/components/Poll/index.jsx
@@ -1,94 +1,215 @@
import React from "react"
import * as antd from "antd"
-import classNames from "classnames"
+import classnames from "classnames"
+import { Icons, createIconRender } from "@components/Icons"
+import { motion } from "framer-motion"
-import { createIconRender } from "@components/Icons"
+import useWsEvents from "@hooks/useWsEvents"
+
+import PostModel from "@models/post"
import "./index.less"
const PollOption = (props) => {
- const { option, editMode, onRemove } = props
+ async function onClick() {
+ if (typeof props.onClick === "function") {
+ await props.onClick(props.option.id)
+ }
+ }
return
{
- editMode &&
}
- {
- !editMode &&
- {option.label}
+
+ {
+ props.checked && createIconRender("FaCheck")
+ }
+
+ {
+ props.showPercentage &&
+ {Math.floor(props.percentage)}%
+
+ }
+
+
+ {props.option.label}
- }
-
- {
- editMode &&
- }
+
}
const Poll = (props) => {
- const { editMode, onClose } = props
+ const { editMode, onClose, formRef } = props
const [options, setOptions] = React.useState(props.options ?? [])
+ const [hasVoted, setHasVoted] = React.useState(false)
+ const [totalVotes, setTotalVotes] = React.useState(0)
- async function addOption() {
- setOptions((prev) => {
- return [
- ...prev,
- {
- label: null
+ useWsEvents({
+ "post.poll.vote": (data) => {
+ const { post_id, option_id, user_id, previous_option_id } = data
+
+ if (post_id !== props.post_id) {
+ return false
+ }
+
+ console.debug(`U[${user_id}] vote to option [${option_id}]`)
+
+ setOptions((prev) => {
+ prev = prev.map((option) => {
+ return option
+ })
+
+ if (user_id === app.userData._id) {
+ // remove all `voted` properties
+ prev = prev.map((option) => {
+ delete option.voted
+
+ option.voted = option.id === option_id
+
+ return option
+ })
}
- ]
+
+ if (previous_option_id) {
+ const previousOptionIndex = prev.findIndex((option) => option.id === previous_option_id)
+
+ if (previousOptionIndex !== -1) {
+ prev[previousOptionIndex].count = prev[previousOptionIndex].count - 1
+ }
+ }
+
+ if (option_id) {
+ const newOptionIndex = prev.findIndex((option) => option.id === option_id)
+
+ if (newOptionIndex !== -1) {
+ prev[newOptionIndex].count += 1
+ }
+ }
+
+ return prev
+ })
+ }
+ }, {
+ socketName: "posts"
+ })
+
+ async function onVote(id) {
+ console.debug(`Voting poll option`, {
+ option_id: id,
+ post_id: props.post_id,
+ })
+
+ await PostModel.votePoll({
+ post_id: props.post_id,
+ option_id: id,
})
}
- async function removeOption(index) {
- setOptions((prev) => {
- return [
- ...prev.slice(0, index),
- ...prev.slice(index + 1)
- ]
- })
- }
+ React.useEffect(() => {
+ if (options) {
+ const totalVotes = options.reduce((sum, option) => {
+ return sum + option.count
+ }, 0)
+
+ setTotalVotes(totalVotes)
+
+ const hasVoted = options.some((option) => {
+ return option.voted
+ })
+
+ setHasVoted(hasVoted)
+ }
+ }, [options])
return
{
- options.map((option, index) => {
+ !editMode && options.map((option, index) => {
+ const percentage = totalVotes > 0 ? (option.count / totalVotes) * 100 : 0
+
return
{
- removeOption(index)
- }}
+ onClick={onVote}
+ checked={option.voted}
+ percentage={percentage}
+ showPercentage={hasVoted}
/>
})
}
{
- editMode &&
-
+
- Add Option
-
+ {(fields, { add, remove }) => {
+ return <>
+ {
+ fields.map((field, index) => {
+ return
+
+
+
+ {
+ fields.length > 1 &&
remove(field.name)}
+ icon={createIconRender("MdRemove")}
+ />
+ }
+
+ })
+ }
+
+
add()}
+ icon={createIconRender("PlusOutlined")}
+ >
+ Add Option
+
+ >
+ }}
+
+
+ }
+
+ {
+ editMode &&
}
+
+ {
+ this.state.data.poll_options &&
+ }
{
@@ -105,6 +107,12 @@ export default class PostCreator extends React.Component {
timestamp: DateTime.local().toISO(),
}
+ if (this.pollRef.current) {
+ let { options } = this.pollRef.current.getFieldsValue()
+
+ payload.poll_options = options.filter((option) => !!option.label)
+ }
+
let response = null
if (this.props.reply_to) {
@@ -496,6 +504,7 @@ export default class PostCreator extends React.Component {
status: "done",
}
}),
+ postPoll: post.poll_options
})
}
// fetch the posting policy
@@ -567,6 +576,7 @@ export default class PostCreator extends React.Component {
+
+