mirror of
https://github.com/CompassConnections/Compass.git
synced 2026-03-24 17:41:27 -04:00
Show number of answers and community importance on prompts
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import {type APIHandler} from 'api/helpers/endpoint'
|
||||
import {Row} from 'common/supabase/utils'
|
||||
import {QuestionWithStats} from 'common/api/types'
|
||||
import {createSupabaseDirectClient} from 'shared/supabase/init'
|
||||
|
||||
export const getCompatibilityQuestions: APIHandler<'get-compatibility-questions'> = async (
|
||||
@@ -31,7 +31,7 @@ export const getCompatibilityQuestions: APIHandler<'get-compatibility-questions'
|
||||
params.push(`%${keyword}%`)
|
||||
}
|
||||
|
||||
const questions = await pg.manyOrNone<Row<'compatibility_prompts'> & {score: number}>(
|
||||
const questions = await pg.manyOrNone<QuestionWithStats>(
|
||||
`
|
||||
SELECT cp.id,
|
||||
cp.answer_type,
|
||||
@@ -39,25 +39,23 @@ export const getCompatibilityQuestions: APIHandler<'get-compatibility-questions'
|
||||
cp.created_time,
|
||||
cp.creator_id,
|
||||
cp.category,
|
||||
cp.community_importance_score * (cp.answer_count::float / (cp.answer_count + 20)) AS community_importance_score,
|
||||
cp.answer_count,
|
||||
|
||||
-- locale-aware fields
|
||||
COALESCE(cpt.question, cp.question) AS question,
|
||||
COALESCE(cpt.question, cp.question) AS question,
|
||||
COALESCE(cpt.multiple_choice_options, cp.multiple_choice_options) AS multiple_choice_options,
|
||||
AVG(
|
||||
POWER(
|
||||
ca.importance + 1 +
|
||||
CASE WHEN ca.explanation IS NULL THEN 1 ELSE 0 END,
|
||||
2
|
||||
)
|
||||
) AS score
|
||||
cp.answer_count,
|
||||
CASE
|
||||
WHEN cp.answer_count IS NULL OR cp.answer_count = 0 THEN 0
|
||||
--- community_importance_score is a weighted sum: max val is 2 * answer_count if everyone marks at the highest level of importance
|
||||
--- So we divide by 2 * answer_count to ensure it's between and 0 and 1
|
||||
--- We damp by 20 to ensure questions with few responders don't get a high score
|
||||
--- The square root is to spread the percent of all questions, since in the early days they don't get higher than 50%.
|
||||
--- It does not impact ranking though.
|
||||
--- TODO: remove the square root when we get more answers
|
||||
ELSE SQRT(cp.community_importance_score::float / (cp.answer_count + 20) / 2) * 100
|
||||
END AS community_importance_percent,
|
||||
0 AS score --- update later if needed
|
||||
|
||||
FROM compatibility_prompts cp
|
||||
|
||||
LEFT JOIN compatibility_answers ca
|
||||
ON cp.id = ca.question_id
|
||||
|
||||
LEFT JOIN compatibility_prompts_translations cpt
|
||||
ON cp.id = cpt.question_id
|
||||
AND cpt.locale = $1
|
||||
@@ -75,7 +73,7 @@ export const getCompatibilityQuestions: APIHandler<'get-compatibility-questions'
|
||||
params,
|
||||
)
|
||||
|
||||
// debug({questions})
|
||||
// console.debug(questions.find((q) => q.id === 275))
|
||||
|
||||
return {
|
||||
status: 'success',
|
||||
|
||||
@@ -50,7 +50,7 @@ describe('getCompatibilityQuestions', () => {
|
||||
expect(sql).toEqual(expect.stringContaining('cp.answer_count'))
|
||||
expect(sql).toEqual(
|
||||
expect.stringContaining(
|
||||
'cp.community_importance_score * (cp.answer_count::float / (cp.answer_count + 20)) AS community_importance_score',
|
||||
'cp.community_importance_score * (cp.answer_count::float / (cp.answer_count + 20)) AS community_importance_percent',
|
||||
),
|
||||
)
|
||||
})
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import {QuestionWithStats} from 'common/api/types' // mqp: very unscientific, just balancing our willingness to accept load
|
||||
import {
|
||||
arraybeSchema,
|
||||
baseProfilesSchema,
|
||||
@@ -19,7 +20,7 @@ import {arrify} from 'common/util/array'
|
||||
import {z} from 'zod'
|
||||
|
||||
import {LikeData, ShipData} from './profile-types'
|
||||
import {FullUser, HiddenProfile} from './user-types' // mqp: very unscientific, just balancing our willingness to accept load
|
||||
import {FullUser, HiddenProfile} from './user-types'
|
||||
|
||||
// mqp: very unscientific, just balancing our willingness to accept load
|
||||
// with user willingness to put up with stale data
|
||||
@@ -574,11 +575,7 @@ export const API = (_apiTypeCheck = {
|
||||
}),
|
||||
returns: {} as {
|
||||
status: 'success'
|
||||
questions: (Row<'compatibility_prompts'> & {
|
||||
answer_count: number
|
||||
score: number
|
||||
community_importance_score?: number
|
||||
})[]
|
||||
questions: QuestionWithStats[]
|
||||
},
|
||||
summary: 'Retrieve compatibility questions and stats',
|
||||
tag: 'Compatibility',
|
||||
|
||||
7
common/src/api/types.ts
Normal file
7
common/src/api/types.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
import {Row} from 'common/supabase/utils'
|
||||
|
||||
export type QuestionWithStats = Omit<Row<'compatibility_prompts'>, 'community_importance_score'> & {
|
||||
answer_count: number
|
||||
score: number
|
||||
community_importance_percent: number
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
import {PlusIcon, XMarkIcon} from '@heroicons/react/24/outline'
|
||||
import {QuestionWithStats} from 'common/api/types'
|
||||
import {MAX_ANSWER_LENGTH} from 'common/envs/constants'
|
||||
import {debug} from 'common/logger'
|
||||
import {MAX_COMPATIBILITY_QUESTION_LENGTH} from 'common/profiles/constants'
|
||||
@@ -13,7 +14,6 @@ import {Modal, MODAL_CLASS} from 'web/components/layout/modal'
|
||||
import {Row} from 'web/components/layout/row'
|
||||
import {ExpandingInput} from 'web/components/widgets/expanding-input'
|
||||
import {useEvent} from 'web/hooks/use-event'
|
||||
import {QuestionWithCountType} from 'web/hooks/use-questions'
|
||||
import {useUser} from 'web/hooks/use-user'
|
||||
import {api} from 'web/lib/api'
|
||||
import {useT} from 'web/lib/locale'
|
||||
@@ -64,7 +64,7 @@ function AddCompatibilityQuestionModal(props: {
|
||||
<CreateCompatibilityModalContent afterAddQuestion={afterAddQuestion} setOpen={setOpen} />
|
||||
) : (
|
||||
<AnswerCompatibilityQuestionContent
|
||||
compatibilityQuestion={dbQuestion as QuestionWithCountType}
|
||||
compatibilityQuestion={dbQuestion as QuestionWithStats}
|
||||
user={user}
|
||||
onSubmit={() => {
|
||||
// setOpen(false)
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import clsx from 'clsx'
|
||||
import {QuestionWithStats} from 'common/api/types'
|
||||
import {User} from 'common/user'
|
||||
import Link from 'next/link'
|
||||
import router from 'next/router'
|
||||
@@ -8,14 +9,13 @@ import {Button} from 'web/components/buttons/button'
|
||||
import {compareBySort, CompatibilitySort} from 'web/components/compatibility/sort-widget'
|
||||
import {Col} from 'web/components/layout/col'
|
||||
import {Modal, MODAL_CLASS, SCROLLABLE_MODAL_CLASS} from 'web/components/layout/modal'
|
||||
import {QuestionWithCountType} from 'web/hooks/use-questions'
|
||||
import {useT} from 'web/lib/locale'
|
||||
|
||||
import {AnswerCompatibilityQuestionContent} from './answer-compatibility-question-content'
|
||||
|
||||
export function AnswerCompatibilityQuestionButton(props: {
|
||||
user: User | null | undefined
|
||||
otherQuestions: QuestionWithCountType[]
|
||||
otherQuestions: QuestionWithStats[]
|
||||
refreshCompatibilityAll: () => void
|
||||
fromSignup?: boolean
|
||||
size?: 'sm' | 'md'
|
||||
@@ -81,7 +81,7 @@ export function CompatibilityPageButton() {
|
||||
|
||||
export function AnswerSkippedCompatibilityQuestionsButton(props: {
|
||||
user: User | null | undefined
|
||||
skippedQuestions: QuestionWithCountType[]
|
||||
skippedQuestions: QuestionWithStats[]
|
||||
refreshCompatibilityAll: () => void
|
||||
fromSignup?: boolean
|
||||
}) {
|
||||
@@ -157,7 +157,7 @@ function AnswerCompatibilityQuestionModal(props: {
|
||||
open: boolean
|
||||
setOpen: (open: boolean) => void
|
||||
user: User
|
||||
otherQuestions: QuestionWithCountType[]
|
||||
otherQuestions: QuestionWithStats[]
|
||||
refreshCompatibilityAll: () => void
|
||||
onClose?: () => void
|
||||
fromSignup?: boolean
|
||||
@@ -175,7 +175,7 @@ function AnswerCompatibilityQuestionModal(props: {
|
||||
const sortedQuestions = useMemo(() => {
|
||||
return [...otherQuestions].sort((a, b) => {
|
||||
return compareBySort(a, b, sort)
|
||||
}) as QuestionWithCountType[]
|
||||
}) as QuestionWithStats[]
|
||||
}, [otherQuestions, sort])
|
||||
|
||||
const handleStartQuestions = () => {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import {RadioGroup} from '@headlessui/react'
|
||||
import {UserIcon} from '@heroicons/react/24/solid'
|
||||
import clsx from 'clsx'
|
||||
import {QuestionWithStats} from 'common/api/types'
|
||||
import {Row as rowFor} from 'common/supabase/utils'
|
||||
import {User} from 'common/user'
|
||||
import {shortenNumber} from 'common/util/format'
|
||||
@@ -15,7 +16,6 @@ import {Row} from 'web/components/layout/row'
|
||||
import {ExpandingInput} from 'web/components/widgets/expanding-input'
|
||||
import {RadioToggleGroup} from 'web/components/widgets/radio-toggle-group'
|
||||
import {Tooltip} from 'web/components/widgets/tooltip'
|
||||
import {QuestionWithCountType} from 'web/hooks/use-questions'
|
||||
import {api} from 'web/lib/api'
|
||||
import {useT} from 'web/lib/locale'
|
||||
import {track} from 'web/lib/service/analytics'
|
||||
@@ -102,7 +102,7 @@ export function getEmptyAnswer(userId: string, questionId: number) {
|
||||
}
|
||||
|
||||
export function AnswerCompatibilityQuestionContent(props: {
|
||||
compatibilityQuestion: QuestionWithCountType
|
||||
compatibilityQuestion: QuestionWithStats
|
||||
user: User
|
||||
index?: number
|
||||
total?: number
|
||||
@@ -158,22 +158,8 @@ export function AnswerCompatibilityQuestionContent(props: {
|
||||
<Col className="min-h-0 w-full gap-4">
|
||||
<Col className="gap-1 shrink-0">
|
||||
<Row>
|
||||
{shortenedPopularity && (
|
||||
<Tooltip
|
||||
text={t(
|
||||
'answers.content.people_answered',
|
||||
'{count} people have answered this question',
|
||||
{count: String(shortenedPopularity)},
|
||||
)}
|
||||
>
|
||||
<Row className="text-ink-500 select-none items-center text-sm">
|
||||
{shortenedPopularity}
|
||||
<UserIcon className="h-4 w-4" />
|
||||
</Row>
|
||||
</Tooltip>
|
||||
)}
|
||||
{isFinite(index!) && isFinite(total!) && (
|
||||
<span className={'ml-16 text-sm'}>
|
||||
<span className={'text-sm'}>
|
||||
<span className="text-ink-600 font-semibold">{index! + 1}</span> / {total}
|
||||
</span>
|
||||
)}
|
||||
@@ -187,6 +173,28 @@ export function AnswerCompatibilityQuestionContent(props: {
|
||||
/>
|
||||
)}
|
||||
</Row>
|
||||
<Row className={''}>
|
||||
{shortenedPopularity && (
|
||||
<Tooltip
|
||||
text={t(
|
||||
'answers.content.people_answered',
|
||||
'{count} people have answered this question',
|
||||
{count: String(shortenedPopularity)},
|
||||
)}
|
||||
>
|
||||
<Row className="select-none items-center text-sm guidance">
|
||||
{shortenedPopularity}
|
||||
<UserIcon className="h-4 w-4" />
|
||||
</Row>
|
||||
</Tooltip>
|
||||
)}
|
||||
{isFinite(compatibilityQuestion.community_importance_percent) && (
|
||||
<span className={'text-sm ml-auto guidance'}>
|
||||
Community Importance: {Math.round(compatibilityQuestion.community_importance_percent)}
|
||||
%
|
||||
</span>
|
||||
)}
|
||||
</Row>
|
||||
<div data-testid="compatibility-question">{compatibilityQuestion.question}</div>
|
||||
</Col>
|
||||
<Col className={clsx(SCROLLABLE_MODAL_CLASS, 'w-full gap-4 flex-1 min-h-0 pr-2')}>
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
import {CheckCircleIcon, XCircleIcon} from '@heroicons/react/24/outline'
|
||||
import clsx from 'clsx'
|
||||
import {QuestionWithStats} from 'common/api/types'
|
||||
import {Row as rowFor} from 'common/supabase/utils'
|
||||
import {User} from 'common/user'
|
||||
import {Col} from 'web/components/layout/col'
|
||||
import {Row} from 'web/components/layout/row'
|
||||
import {shortenName} from 'web/components/widgets/user-link'
|
||||
import {QuestionWithCountType} from 'web/hooks/use-questions'
|
||||
import {useT} from 'web/lib/locale'
|
||||
|
||||
export function PreferredList(props: {
|
||||
question: QuestionWithCountType
|
||||
question: QuestionWithStats
|
||||
answer: rowFor<'compatibility_answers'>
|
||||
comparedAnswer: rowFor<'compatibility_answers'>
|
||||
comparedUser: User
|
||||
@@ -65,7 +65,7 @@ export function PreferredList(props: {
|
||||
}
|
||||
|
||||
export function PreferredListNoComparison(props: {
|
||||
question: QuestionWithCountType
|
||||
question: QuestionWithStats
|
||||
answer: rowFor<'compatibility_answers'>
|
||||
}) {
|
||||
const {question, answer} = props
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import {PencilIcon, TrashIcon} from '@heroicons/react/24/outline'
|
||||
import {UserIcon} from '@heroicons/react/24/solid'
|
||||
import clsx from 'clsx'
|
||||
import {QuestionWithStats} from 'common/api/types'
|
||||
import {
|
||||
getAnswerCompatibility,
|
||||
getScoredAnswerCompatibility,
|
||||
@@ -7,6 +9,7 @@ import {
|
||||
import {Profile} from 'common/profiles/profile'
|
||||
import {Row as rowFor} from 'common/supabase/utils'
|
||||
import {User} from 'common/user'
|
||||
import {shortenNumber} from 'common/util/format'
|
||||
import {keyBy, partition, sortBy} from 'lodash'
|
||||
import {useEffect, useState} from 'react'
|
||||
import toast from 'react-hot-toast'
|
||||
@@ -24,13 +27,13 @@ import {CompatibleBadge} from 'web/components/widgets/compatible-badge'
|
||||
import {Input} from 'web/components/widgets/input'
|
||||
import {Linkify} from 'web/components/widgets/linkify'
|
||||
import {Pagination} from 'web/components/widgets/pagination'
|
||||
import {Tooltip} from 'web/components/widgets/tooltip'
|
||||
import {shortenName} from 'web/components/widgets/user-link'
|
||||
import {useIsLooking} from 'web/hooks/use-is-looking'
|
||||
import {usePersistentInMemoryState} from 'web/hooks/use-persistent-in-memory-state'
|
||||
import {useProfile} from 'web/hooks/use-profile'
|
||||
import {useCompatibleProfiles} from 'web/hooks/use-profiles'
|
||||
import {
|
||||
QuestionWithCountType,
|
||||
useCompatibilityQuestionsWithAnswerCount,
|
||||
useUserCompatibilityAnswers,
|
||||
} from 'web/hooks/use-questions'
|
||||
@@ -59,13 +62,13 @@ import {PreferredList, PreferredListNoComparison} from './compatibility-question
|
||||
const NUM_QUESTIONS_TO_SHOW = 8
|
||||
|
||||
export function separateQuestionsArray(
|
||||
questions: QuestionWithCountType[],
|
||||
questions: QuestionWithStats[],
|
||||
skippedAnswerQuestionIds: Set<number>,
|
||||
answeredQuestionIds: Set<number>,
|
||||
) {
|
||||
const skippedQuestions: QuestionWithCountType[] = []
|
||||
const answeredQuestions: QuestionWithCountType[] = []
|
||||
const otherQuestions: QuestionWithCountType[] = []
|
||||
const skippedQuestions: QuestionWithStats[] = []
|
||||
const answeredQuestions: QuestionWithStats[] = []
|
||||
const otherQuestions: QuestionWithStats[] = []
|
||||
|
||||
questions.forEach((q) => {
|
||||
if (skippedAnswerQuestionIds.has(q.id)) {
|
||||
@@ -86,8 +89,10 @@ export function CompatibilityQuestionsDisplay(props: {
|
||||
profile: Profile
|
||||
fromSignup?: boolean
|
||||
fromProfilePage?: Profile
|
||||
showCommunityInfo?: boolean
|
||||
}) {
|
||||
const {isCurrentUser, user, fromSignup, fromProfilePage, profile} = props
|
||||
const {isCurrentUser, user, fromSignup, fromProfilePage, profile, showCommunityInfo} = props
|
||||
|
||||
const t = useT()
|
||||
|
||||
const currentUser = useUser()
|
||||
@@ -274,6 +279,7 @@ export function CompatibilityQuestionsDisplay(props: {
|
||||
refreshCompatibilityAll={refreshCompatibilityAll}
|
||||
profile={profile}
|
||||
fromProfilePage={fromProfilePage}
|
||||
showCommunityInfo={showCommunityInfo}
|
||||
/>
|
||||
)
|
||||
})}
|
||||
@@ -318,13 +324,14 @@ export function CompatibilityQuestionsDisplay(props: {
|
||||
|
||||
export function CompatibilityAnswerBlock(props: {
|
||||
answer?: rowFor<'compatibility_answers'>
|
||||
yourQuestions: QuestionWithCountType[]
|
||||
question?: QuestionWithCountType
|
||||
yourQuestions: QuestionWithStats[]
|
||||
question?: QuestionWithStats
|
||||
user: User
|
||||
isCurrentUser: boolean
|
||||
profile?: Profile
|
||||
refreshCompatibilityAll: () => void
|
||||
fromProfilePage?: Profile
|
||||
showCommunityInfo?: boolean
|
||||
}) {
|
||||
const {
|
||||
answer,
|
||||
@@ -335,6 +342,9 @@ export function CompatibilityAnswerBlock(props: {
|
||||
refreshCompatibilityAll,
|
||||
fromProfilePage,
|
||||
} = props
|
||||
|
||||
const showCommunityInfo = props.showCommunityInfo === undefined ? true : props.showCommunityInfo
|
||||
|
||||
const question = props.question || yourQuestions.find((q) => q.id === answer?.question_id)
|
||||
const [editOpen, setEditOpen] = useState<boolean>(false)
|
||||
const currentUser = useUser()
|
||||
@@ -377,6 +387,9 @@ export function CompatibilityAnswerBlock(props: {
|
||||
|
||||
const isAnswered = answer && answer.multiple_choice > -1
|
||||
const isSkipped = answer && answer.importance == -1
|
||||
|
||||
const shortenedPopularity = question.answer_count ? shortenNumber(question.answer_count) : null
|
||||
|
||||
return (
|
||||
<Col
|
||||
data-testid="profile-compatibility-section"
|
||||
@@ -530,6 +543,29 @@ export function CompatibilityAnswerBlock(props: {
|
||||
)}
|
||||
{/*{question.importance_score == 0 && <div className="text-ink-500 text-sm">Core Question</div>}*/}
|
||||
</Col>
|
||||
{showCommunityInfo && (
|
||||
<Row className={'mt-[-20px]'}>
|
||||
{shortenedPopularity && (
|
||||
<Tooltip
|
||||
text={t(
|
||||
'answers.content.people_answered',
|
||||
'{count} people have answered this question',
|
||||
{count: String(shortenedPopularity)},
|
||||
)}
|
||||
>
|
||||
<Row className="select-none items-center text-sm guidance">
|
||||
{shortenedPopularity}
|
||||
<UserIcon className="h-4 w-4" />
|
||||
</Row>
|
||||
</Tooltip>
|
||||
)}
|
||||
{isFinite(question.community_importance_percent) && (
|
||||
<span className={'text-sm ml-auto guidance'}>
|
||||
Community Importance: {Math.round(question.community_importance_percent)}%
|
||||
</span>
|
||||
)}
|
||||
</Row>
|
||||
)}
|
||||
<Modal open={editOpen} setOpen={setEditOpen}>
|
||||
<Col className={MODAL_CLASS}>
|
||||
<AnswerCompatibilityQuestionContent
|
||||
@@ -551,7 +587,7 @@ export function CompatibilityAnswerBlock(props: {
|
||||
}
|
||||
|
||||
function CompatibilityDisplay(props: {
|
||||
question: QuestionWithCountType
|
||||
question: QuestionWithStats
|
||||
profile1?: Profile
|
||||
profile2: Profile
|
||||
answer1: rowFor<'compatibility_answers'>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import {ArrowLeftIcon, PlusIcon} from '@heroicons/react/24/outline'
|
||||
import clsx from 'clsx'
|
||||
import {QuestionWithStats} from 'common/api/types'
|
||||
import {User} from 'common/user'
|
||||
import {TbMessage} from 'react-icons/tb'
|
||||
import {Button} from 'web/components/buttons/button'
|
||||
@@ -7,7 +8,6 @@ import {Col} from 'web/components/layout/col'
|
||||
import {Modal, MODAL_CLASS, SCROLLABLE_MODAL_CLASS} from 'web/components/layout/modal'
|
||||
import {Row} from 'web/components/layout/row'
|
||||
import {usePersistentInMemoryState} from 'web/hooks/use-persistent-in-memory-state'
|
||||
import {QuestionWithCountType} from 'web/hooks/use-questions'
|
||||
import {useT} from 'web/lib/locale'
|
||||
|
||||
import {IndividualQuestionRow} from '../questions-form'
|
||||
@@ -15,7 +15,7 @@ import {OtherProfileAnswers} from './other-profile-answers'
|
||||
|
||||
export function AddQuestionButton(props: {
|
||||
isFirstQuestion?: boolean
|
||||
questions: QuestionWithCountType[]
|
||||
questions: QuestionWithStats[]
|
||||
user: User
|
||||
refreshAnswers: () => void
|
||||
}) {
|
||||
@@ -44,20 +44,20 @@ export function AddQuestionButton(props: {
|
||||
function AddQuestionModal(props: {
|
||||
open: boolean
|
||||
setOpen: (open: boolean) => void
|
||||
questions: QuestionWithCountType[]
|
||||
questions: QuestionWithStats[]
|
||||
user: User
|
||||
refreshAnswers: () => void
|
||||
}) {
|
||||
const {open, setOpen, questions, user, refreshAnswers} = props
|
||||
const addableQuestions = questions.filter((q) => q.answer_type === 'free_response')
|
||||
const [selectedQuestion, setSelectedQuestion] =
|
||||
usePersistentInMemoryState<QuestionWithCountType | null>(
|
||||
usePersistentInMemoryState<QuestionWithStats | null>(
|
||||
null,
|
||||
`selected-added-question-${user.id}}`,
|
||||
)
|
||||
|
||||
const [expandedQuestion, setExpandedQuestion] =
|
||||
usePersistentInMemoryState<QuestionWithCountType | null>(
|
||||
usePersistentInMemoryState<QuestionWithStats | null>(
|
||||
null,
|
||||
`selected-expanded-question-${user.id}}`,
|
||||
)
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import {PencilIcon, XMarkIcon} from '@heroicons/react/24/outline'
|
||||
import {QuestionWithStats} from 'common/api/types'
|
||||
import {Profile} from 'common/profiles/profile'
|
||||
import {Row as rowFor} from 'common/supabase/utils'
|
||||
import {User} from 'common/user'
|
||||
@@ -11,11 +12,7 @@ import {Modal, MODAL_CLASS, SCROLLABLE_MODAL_CLASS} from 'web/components/layout/
|
||||
import {Row} from 'web/components/layout/row'
|
||||
import {Linkify} from 'web/components/widgets/linkify'
|
||||
import {shortenName} from 'web/components/widgets/user-link'
|
||||
import {
|
||||
QuestionWithCountType,
|
||||
useFRQuestionsWithAnswerCount,
|
||||
useUserAnswers,
|
||||
} from 'web/hooks/use-questions'
|
||||
import {useFRQuestionsWithAnswerCount, useUserAnswers} from 'web/hooks/use-questions'
|
||||
import {useT} from 'web/lib/locale'
|
||||
import {deleteAnswer} from 'web/lib/supabase/answers'
|
||||
|
||||
@@ -91,7 +88,7 @@ export function FreeResponseDisplay(props: {
|
||||
|
||||
function AnswerBlock(props: {
|
||||
answer: rowFor<'compatibility_answers_free'>
|
||||
questions: QuestionWithCountType[]
|
||||
questions: QuestionWithStats[]
|
||||
isCurrentUser: boolean
|
||||
user: User
|
||||
refreshAnswers: () => void
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import clsx from 'clsx'
|
||||
import {QuestionWithStats} from 'common/api/types'
|
||||
import {convertGender, Gender} from 'common/gender'
|
||||
import {User} from 'common/user'
|
||||
import {capitalize} from 'lodash'
|
||||
@@ -9,12 +10,11 @@ import {Linkify} from 'web/components/widgets/linkify'
|
||||
import {CompassLoadingIndicator} from 'web/components/widgets/loading-indicator'
|
||||
import {UserLink} from 'web/components/widgets/user-link'
|
||||
import {useOtherAnswers} from 'web/hooks/use-other-answers'
|
||||
import {QuestionWithCountType} from 'web/hooks/use-questions'
|
||||
import {useT} from 'web/lib/locale'
|
||||
import {shortenedFromNow} from 'web/lib/util/shortenedFromNow'
|
||||
|
||||
export function OtherProfileAnswers(props: {
|
||||
question: QuestionWithCountType
|
||||
question: QuestionWithStats
|
||||
user?: User
|
||||
className?: string
|
||||
}) {
|
||||
|
||||
@@ -21,6 +21,7 @@ export function ProfileAnswers(props: {
|
||||
profile={profile}
|
||||
fromSignup={fromSignup}
|
||||
fromProfilePage={fromProfilePage}
|
||||
showCommunityInfo={false}
|
||||
/>
|
||||
{/*<FreeResponseDisplay*/}
|
||||
{/* isCurrentUser={isCurrentUser}*/}
|
||||
|
||||
@@ -80,8 +80,8 @@ export function compareBySort(a: any, b: any, sort: CompatibilitySort) {
|
||||
if (sort === 'random') {
|
||||
return Math.random() - 0.5
|
||||
} else if (sort === 'community_importance') {
|
||||
const rateA = (a?.community_importance_score ?? 0) / Math.max(a?.answer_count ?? 1, 1)
|
||||
const rateB = (b?.community_importance_score ?? 0) / Math.max(b?.answer_count ?? 1, 1)
|
||||
const rateA = a?.community_importance_percent ?? 0
|
||||
const rateB = b?.community_importance_percent ?? 0
|
||||
return rateB - rateA
|
||||
} else if (sort === 'most_answered') {
|
||||
return (b?.answer_count ?? 0) - (a?.answer_count ?? 0)
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import {QuestionWithStats} from 'common/api/types'
|
||||
import {Row} from 'common/supabase/utils'
|
||||
import {sortBy} from 'lodash'
|
||||
import {useEffect, useState} from 'react'
|
||||
@@ -75,12 +76,6 @@ export const useUserCompatibilityAnswers = (userId: string | undefined) => {
|
||||
return {refreshCompatibilityAnswers, compatibilityAnswers}
|
||||
}
|
||||
|
||||
export type QuestionWithCountType = Row<'compatibility_prompts'> & {
|
||||
answer_count: number
|
||||
score: number
|
||||
community_importance_score?: number
|
||||
}
|
||||
|
||||
export const useFRQuestionsWithAnswerCount = () => {
|
||||
const [FRquestionsWithCount, setFRQuestionsWithCount] = usePersistentInMemoryState<any>(
|
||||
[],
|
||||
@@ -93,14 +88,14 @@ export const useFRQuestionsWithAnswerCount = () => {
|
||||
})
|
||||
}, [])
|
||||
|
||||
return FRquestionsWithCount as QuestionWithCountType[]
|
||||
return FRquestionsWithCount as QuestionWithStats[]
|
||||
}
|
||||
|
||||
export const useCompatibilityQuestionsWithAnswerCount = () => {
|
||||
const {locale} = useLocale()
|
||||
const firebaseUser = useFirebaseUser()
|
||||
const [compatibilityQuestions, setCompatibilityQuestions] = usePersistentInMemoryState<
|
||||
QuestionWithCountType[]
|
||||
QuestionWithStats[]
|
||||
>([], `compatibility-questions-with-count`)
|
||||
const [isLoading, setIsLoading] = useState(true)
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ export type QuestionWithAnswer = Question & {
|
||||
answer?: Row<'compatibility_answers'>
|
||||
answer_count: number
|
||||
score: number
|
||||
community_importance_score?: number
|
||||
community_importance_percent: number
|
||||
}
|
||||
|
||||
export const getAllQuestions = async () => {
|
||||
|
||||
Reference in New Issue
Block a user