Skip to content

Commit a9825ed

Browse files
committed
Hide compatibility questions card if empty
1 parent 9b4e9dd commit a9825ed

4 files changed

Lines changed: 107 additions & 84 deletions

File tree

android/app/build.gradle

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ android {
1111
applicationId "com.compassconnections.app"
1212
minSdkVersion rootProject.ext.minSdkVersion
1313
targetSdkVersion rootProject.ext.targetSdkVersion
14-
versionCode 117
15-
versionName "1.28.0"
14+
versionCode 118
15+
versionName "1.29.0"
1616
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
1717
aaptOptions {
1818
// Files and dirs to omit from the packaged assets dir, modified to accommodate modern web apps.

web/components/answers/compatibility-questions-display.tsx

Lines changed: 42 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import {Profile} from 'common/profiles/profile'
1111
import {Row as rowFor} from 'common/supabase/utils'
1212
import {User} from 'common/user'
1313
import {shortenNumber} from 'common/util/format'
14-
import {keyBy, partition, sortBy} from 'lodash'
14+
import {keyBy, sortBy} from 'lodash'
1515
import {PinIcon} from 'lucide-react'
1616
import {useCallback, useEffect, useMemo, useState} from 'react'
1717
import toast from 'react-hot-toast'
@@ -31,15 +31,11 @@ import {Linkify} from 'web/components/widgets/linkify'
3131
import {Pagination} from 'web/components/widgets/pagination'
3232
import {Tooltip} from 'web/components/widgets/tooltip'
3333
import {shortenName} from 'web/components/widgets/user-link'
34-
import {useIsLooking} from 'web/hooks/use-is-looking'
3534
import {usePersistentInMemoryState} from 'web/hooks/use-persistent-in-memory-state'
3635
import {usePinnedQuestionIds} from 'web/hooks/use-pinned-question-ids'
3736
import {useProfile} from 'web/hooks/use-profile'
3837
import {useCompatibleProfiles} from 'web/hooks/use-profiles'
39-
import {
40-
useCompatibilityQuestionsWithAnswerCount,
41-
useUserCompatibilityAnswers,
42-
} from 'web/hooks/use-questions'
38+
import {useCompatibilityQuestionGroups, useUserCompatibilityAnswers} from 'web/hooks/use-questions'
4339
import {useUser} from 'web/hooks/use-user'
4440
import {useT} from 'web/lib/locale'
4541
import {db} from 'web/lib/supabase/db'
@@ -65,29 +61,6 @@ import {PinQuestionButton} from './pin-question-button'
6561
const NUM_QUESTIONS_TO_SHOW = 8
6662
const NUM_PINNED_QUESTIONS_TO_SHOW = 4
6763

68-
export function separateQuestionsArray(
69-
questions: QuestionWithStats[],
70-
skippedAnswerQuestionIds: Set<number>,
71-
answeredQuestionIds: Set<number>,
72-
) {
73-
debug('Refreshing questions array')
74-
const skippedQuestions: QuestionWithStats[] = []
75-
const answeredQuestions: QuestionWithStats[] = []
76-
const otherQuestions: QuestionWithStats[] = []
77-
78-
questions.forEach((q) => {
79-
if (skippedAnswerQuestionIds.has(q.id)) {
80-
skippedQuestions.push(q)
81-
} else if (answeredQuestionIds.has(q.id)) {
82-
answeredQuestions.push(q)
83-
} else {
84-
otherQuestions.push(q)
85-
}
86-
})
87-
88-
return {skippedQuestions, answeredQuestions, otherQuestions}
89-
}
90-
9164
export function CompatibilityQuestionsDisplay(props: {
9265
isCurrentUser: boolean
9366
user: User
@@ -106,36 +79,24 @@ export function CompatibilityQuestionsDisplay(props: {
10679

10780
const {pinnedQuestionIds, refreshPinnedQuestionIds} = usePinnedQuestionIds()
10881

109-
const {refreshCompatibilityQuestions, compatibilityQuestions} =
110-
useCompatibilityQuestionsWithAnswerCount()
111-
112-
const {refreshCompatibilityAnswers, compatibilityAnswers} = useUserCompatibilityAnswers(user.id)
113-
114-
const {answers, skippedQuestions, answeredQuestions, otherQuestions} = useMemo(() => {
115-
debug('Refreshing questions')
116-
const [skippedAnswers, answers] = partition(
117-
compatibilityAnswers,
118-
(answer) => answer.importance == -1,
119-
)
120-
const answeredQuestionIds = new Set(answers.map((answer) => answer.question_id))
121-
const skippedAnswerQuestionIds = new Set(skippedAnswers.map((answer) => answer.question_id))
122-
const {skippedQuestions, answeredQuestions, otherQuestions} = separateQuestionsArray(
123-
compatibilityQuestions,
124-
skippedAnswerQuestionIds,
125-
answeredQuestionIds,
126-
)
127-
return {answers, skippedQuestions, answeredQuestions, otherQuestions}
128-
}, [compatibilityAnswers, compatibilityQuestions])
82+
const {
83+
answers,
84+
skippedQuestions,
85+
answeredQuestions,
86+
otherQuestions,
87+
compatibilityQuestions,
88+
refreshCompatibilityAnswers,
89+
refreshCompatibilityQuestions,
90+
} = useCompatibilityQuestionGroups(user.id)
12991

13092
const refreshCompatibilityAll = useCallback(() => {
13193
refreshCompatibilityAnswers()
13294
refreshCompatibilityQuestions()
13395
refreshPinnedQuestionIds()
13496
}, [refreshCompatibilityAnswers, refreshCompatibilityQuestions, refreshPinnedQuestionIds])
13597

136-
const isLooking = useIsLooking()
13798
const [sort, setSort] = usePersistentInMemoryState<CompatibilitySort>(
138-
!isLooking && !fromProfilePage ? 'their_important' : 'your_important',
99+
isCurrentUser ? 'your_important' : 'their_important',
139100
`compatibility-sort-${user.id}`,
140101
)
141102
const [searchTerm, setSearchTerm] = useState('')
@@ -241,40 +202,42 @@ export function CompatibilityQuestionsDisplay(props: {
241202
)}
242203
<Row className="flex-wrap items-center justify-between gap-x-6 gap-y-4">
243204
{answeredQuestions.length > 0 && (
244-
<div className="relative mt-3 w-full max-w-[50%] xl:max-w-[400px]">
245-
{/*<input*/}
246-
{/* type="text"*/}
247-
{/* placeholder={t('answers.search_placeholder', 'Search prompts...')}*/}
248-
{/* value={searchTerm}*/}
249-
{/* onChange={(e) => {*/}
250-
{/* setSearchTerm(e.target.value)*/}
251-
{/* setPage(0)*/}
252-
{/* }}*/}
253-
{/* className="h-8 pl-7 pr-2 text-sm border border-ink-300 rounded-xl bg-canvas-50 focus:outline-none focus:ring-1 focus:ring-primary-500 w-48 transition-all"*/}
254-
{/*/>*/}
255-
<Input
256-
value={searchTerm}
257-
placeholder={t('answers.search_placeholder', 'Search prompts...')}
258-
className={'w-full'}
259-
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
260-
setSearchTerm(e.target.value)
261-
}}
262-
searchIcon
205+
<>
206+
<div className="relative mt-3 w-full max-w-[50%] xl:max-w-[400px]">
207+
{/*<input*/}
208+
{/* type="text"*/}
209+
{/* placeholder={t('answers.search_placeholder', 'Search prompts...')}*/}
210+
{/* value={searchTerm}*/}
211+
{/* onChange={(e) => {*/}
212+
{/* setSearchTerm(e.target.value)*/}
213+
{/* setPage(0)*/}
214+
{/* }}*/}
215+
{/* className="h-8 pl-7 pr-2 text-sm border border-ink-300 rounded-xl bg-canvas-50 focus:outline-none focus:ring-1 focus:ring-primary-500 w-48 transition-all"*/}
216+
{/*/>*/}
217+
<Input
218+
value={searchTerm}
219+
placeholder={t('answers.search_placeholder', 'Search prompts...')}
220+
className={'w-full'}
221+
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
222+
setSearchTerm(e.target.value)
223+
}}
224+
searchIcon
225+
/>
226+
</div>
227+
<CompatibilitySortWidget
228+
className="text-sm sm:flex mt-4"
229+
sort={sort}
230+
setSort={setSort}
231+
user={user}
232+
profile={profile}
263233
/>
264-
</div>
234+
</>
265235
)}
266-
<CompatibilitySortWidget
267-
className="text-sm sm:flex mt-4"
268-
sort={sort}
269-
setSort={setSort}
270-
user={user}
271-
profile={profile}
272-
/>
273236
{compatibilityScore && (
274237
<CompatibleBadge compatibility={compatibilityScore} className={'mt-5 mr-4'} />
275238
)}
276239
</Row>
277-
{answeredQuestions.length <= 0 ? (
240+
{answeredQuestions.length == 0 ? (
278241
<span className="text-ink-600 text-sm">
279242
{isCurrentUser
280243
? t(

web/components/profile/profile-info.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import {Subtitle} from 'web/components/widgets/subtitle'
2121
import {shortenName} from 'web/components/widgets/user-link'
2222
import {useGetter} from 'web/hooks/use-getter'
2323
import {useHiddenProfiles} from 'web/hooks/use-hidden-profiles'
24+
import {useCompatibilityQuestionGroups} from 'web/hooks/use-questions'
2425
import {useUser} from 'web/hooks/use-user'
2526
import {useUserActivity} from 'web/hooks/use-user-activity'
2627
import {User} from 'web/lib/firebase/users'
@@ -327,6 +328,9 @@ function ProfileContent(props: {
327328
const isCurrentUser = currentUser?.id === user.id
328329
const t = useT()
329330

331+
const {answeredQuestions} = useCompatibilityQuestionGroups(user.id)
332+
const showCompatibilityPrompts = currentUser && (isCurrentUser || answeredQuestions.length > 0)
333+
330334
return (
331335
<>
332336
<div
@@ -374,7 +378,7 @@ function ProfileContent(props: {
374378

375379
<ProfileCarousel profile={profile} />
376380

377-
{currentUser && (
381+
{showCompatibilityPrompts && (
378382
<ProfileCard
379383
className="p-5"
380384
title={

web/hooks/use-questions.ts

Lines changed: 58 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import {QuestionWithStats} from 'common/api/types'
2+
import {debug} from 'common/logger'
23
import {Row} from 'common/supabase/utils'
3-
import {sortBy} from 'lodash'
4-
import {useEffect, useState} from 'react'
4+
import {partition, sortBy} from 'lodash'
5+
import {useEffect, useMemo, useState} from 'react'
56
import {useFirebaseUser} from 'web/hooks/use-firebase-user'
67
import {usePersistentInMemoryState} from 'web/hooks/use-persistent-in-memory-state'
78
import {api} from 'web/lib/api'
@@ -118,3 +119,58 @@ export const useCompatibilityQuestionsWithAnswerCount = () => {
118119
isLoading,
119120
}
120121
}
122+
123+
export function separateQuestionsArray(
124+
questions: QuestionWithStats[],
125+
skippedAnswerQuestionIds: Set<number>,
126+
answeredQuestionIds: Set<number>,
127+
) {
128+
debug('Refreshing questions array')
129+
const skippedQuestions: QuestionWithStats[] = []
130+
const answeredQuestions: QuestionWithStats[] = []
131+
const otherQuestions: QuestionWithStats[] = []
132+
133+
questions.forEach((q) => {
134+
if (skippedAnswerQuestionIds.has(q.id)) {
135+
skippedQuestions.push(q)
136+
} else if (answeredQuestionIds.has(q.id)) {
137+
answeredQuestions.push(q)
138+
} else {
139+
otherQuestions.push(q)
140+
}
141+
})
142+
143+
return {skippedQuestions, answeredQuestions, otherQuestions}
144+
}
145+
146+
// Single source of truth for a user's compatibility answers split into
147+
// answered / skipped / other groups. Both the display component and the
148+
// profile-card visibility check read this (shared in-memory cache, no refetch).
149+
export const useCompatibilityQuestionGroups = (userId: string | undefined) => {
150+
const {refreshCompatibilityAnswers, compatibilityAnswers} = useUserCompatibilityAnswers(userId)
151+
const {refreshCompatibilityQuestions, compatibilityQuestions} =
152+
useCompatibilityQuestionsWithAnswerCount()
153+
154+
const groups = useMemo(() => {
155+
debug('Refreshing questions')
156+
const [skippedAnswers, answers] = partition(
157+
compatibilityAnswers,
158+
(answer) => answer.importance == -1,
159+
)
160+
return {
161+
answers,
162+
...separateQuestionsArray(
163+
compatibilityQuestions,
164+
new Set(skippedAnswers.map((answer) => answer.question_id)),
165+
new Set(answers.map((answer) => answer.question_id)),
166+
),
167+
}
168+
}, [compatibilityAnswers, compatibilityQuestions])
169+
170+
return {
171+
...groups,
172+
compatibilityQuestions,
173+
refreshCompatibilityAnswers,
174+
refreshCompatibilityQuestions,
175+
}
176+
}

0 commit comments

Comments
 (0)