Add romantic type in filters

This commit is contained in:
MartinBraquet
2025-10-19 21:25:17 +02:00
parent 92980f7c79
commit 552af7bb6b
8 changed files with 151 additions and 11 deletions

View File

@@ -21,6 +21,7 @@ export type FilterFields = {
ProfileRow,
| 'wants_kids_strength'
| 'pref_relation_styles'
| 'pref_romantic_styles'
| 'is_smoker'
| 'has_kids'
| 'pref_gender'
@@ -60,6 +61,7 @@ export const initialFilters: Partial<FilterFields> = {
wants_kids_strength: undefined,
is_smoker: undefined,
pref_relation_styles: undefined,
pref_romantic_styles: undefined,
pref_gender: undefined,
shortBio: undefined,
orderBy: 'created_time',

View File

@@ -1,5 +1,5 @@
import {ChevronDownIcon, ChevronUpIcon} from '@heroicons/react/outline'
import {RelationshipType} from 'web/lib/util/convert-relationship-type'
import {RelationshipType, RomanticType} from 'web/lib/util/convert-relationship-type'
import {ReactNode} from 'react'
import {FaUserGroup} from 'react-icons/fa6'
import {Col} from 'web/components/layout/col'
@@ -19,6 +19,8 @@ import DropdownMenu from "web/components/comments/dropdown-menu";
import {KidsLabel, wantsKidsLabelsWithIcon} from "web/components/filters/wants-kids-filter";
import {hasKidsLabels} from "common/has-kids";
import {HasKidsLabel} from "web/components/filters/has-kids-filter";
import {RomanticFilter, RomanticFilterText} from "web/components/filters/romantic-filter";
import {FaHeart} from "react-icons/fa";
export function DesktopFilters(props: {
filters: Partial<FilterFields>
@@ -28,6 +30,7 @@ export function DesktopFilters(props: {
setYourFilters: (checked: boolean) => void
isYourFilters: boolean
locationFilterProps: LocationFilterProps
includeRelationshipFilters: boolean | undefined
}) {
const {
filters,
@@ -37,6 +40,7 @@ export function DesktopFilters(props: {
setYourFilters,
isYourFilters,
locationFilterProps,
includeRelationshipFilters,
} = props
return (
@@ -47,6 +51,7 @@ export function DesktopFilters(props: {
on={isYourFilters}
hidden={!youProfile}
/>
{/* CONNECTION */}
<CustomizeableDropdown
buttonContent={(open) => (
@@ -73,6 +78,7 @@ export function DesktopFilters(props: {
popoverClassName="bg-canvas-50"
menuWidth="w-50"
/>
{/* LOCATION */}
<CustomizeableDropdown
buttonContent={(open: boolean) => (
@@ -142,7 +148,7 @@ export function DesktopFilters(props: {
popoverClassName="bg-canvas-50"
/>
{/* PREFERRED GENDER */}
{/* GENDER THEY SEEK */}
<CustomizeableDropdown
buttonContent={(open: boolean) => (
<DropdownButton
@@ -163,6 +169,35 @@ export function DesktopFilters(props: {
popoverClassName="bg-canvas-50"
/>
{includeRelationshipFilters && <>
{/* CONNECTION */}
<CustomizeableDropdown
buttonContent={(open) => (
<DropdownButton
open={open}
content={
<Row className="items-center gap-1">
<FaHeart className="h-4 w-4"/>
<RomanticFilterText
relationship={
filters.pref_romantic_styles as
| RomanticType[]
| undefined
}
highlightedClass={open ? 'text-primary-500' : undefined}
/>
</Row>
}
/>
)}
dropdownMenuContent={
<RomanticFilter filters={filters} updateFilter={updateFilter}/>
}
popoverClassName="bg-canvas-50"
menuWidth="w-50"
/>
{/* WANTS KIDS */}
<DropdownMenu
items={[
@@ -253,6 +288,9 @@ export function DesktopFilters(props: {
menuWidth="w-40"
/>
</>
}
{/* Short Bios */}
<ShortBioToggle
updateFilter={updateFilter}

View File

@@ -10,7 +10,7 @@ import {RelationshipFilter, RelationshipFilterText,} from './relationship-filter
import {MyMatchesToggle} from './my-matches-toggle'
import {Profile} from 'common/love/profile'
import {Gender} from 'common/gender'
import {RelationshipType} from 'web/lib/util/convert-relationship-type'
import {RelationshipType, RomanticType} from 'web/lib/util/convert-relationship-type'
import {FilterFields} from "common/filters";
import {ShortBioToggle} from "web/components/filters/short-bio-toggle";
import {PrefGenderFilter, PrefGenderFilterText} from "./pref-gender-filter"
@@ -19,6 +19,7 @@ import {wantsKidsLabels} from "common/wants-kids";
import {FaChild} from "react-icons/fa"
import {HasKidsFilter, HasKidsLabel} from "./has-kids-filter"
import {hasKidsLabels} from "common/has-kids";
import {RomanticFilter, RomanticFilterText} from "web/components/filters/romantic-filter";
function MobileFilters(props: {
filters: Partial<FilterFields>
@@ -28,6 +29,7 @@ function MobileFilters(props: {
setYourFilters: (checked: boolean) => void
isYourFilters: boolean
locationFilterProps: LocationFilterProps
includeRelationshipFilters: boolean | undefined
}) {
const {
filters,
@@ -37,6 +39,7 @@ function MobileFilters(props: {
setYourFilters,
isYourFilters,
locationFilterProps,
includeRelationshipFilters,
} = props
const [openFilter, setOpenFilter] = useState<string | undefined>(undefined)
@@ -60,6 +63,7 @@ function MobileFilters(props: {
hidden={!youProfile}
/>
</Col>
{/* RELATIONSHIP STYLE */}
<MobileFilterSection
title="Seeking"
@@ -79,6 +83,7 @@ function MobileFilters(props: {
>
<RelationshipFilter filters={filters} updateFilter={updateFilter}/>
</MobileFilterSection>
{/* LOCATION */}
<MobileFilterSection
title="Location"
@@ -103,6 +108,7 @@ function MobileFilters(props: {
locationFilterProps={locationFilterProps}
/>
</MobileFilterSection>
{/* AGE RANGE */}
<MobileFilterSection
title="Age"
@@ -122,6 +128,7 @@ function MobileFilters(props: {
>
<AgeFilter filters={filters} updateFilter={updateFilter}/>
</MobileFilterSection>
{/* GENDER */}
<MobileFilterSection
title="Gender"
@@ -142,7 +149,7 @@ function MobileFilters(props: {
{/* PREFERRED GENDER */}
<MobileFilterSection
title="Interested in"
title="Gender they seek"
openFilter={openFilter}
setOpenFilter={setOpenFilter}
isActive={hasAny(filters.pref_gender)}
@@ -158,6 +165,28 @@ function MobileFilters(props: {
<PrefGenderFilter filters={filters} updateFilter={updateFilter}/>
</MobileFilterSection>
{includeRelationshipFilters && <>
{/* ROMANTIC STYLE */}
<MobileFilterSection
title="Style"
openFilter={openFilter}
setOpenFilter={setOpenFilter}
isActive={hasAny(filters.pref_romantic_styles || undefined)}
selection={
<RomanticFilterText
relationship={filters.pref_romantic_styles as RomanticType[]}
highlightedClass={
hasAny(filters.pref_romantic_styles || undefined)
? 'text-primary-600'
: 'text-ink-900'
}
/>
}
>
<RomanticFilter filters={filters} updateFilter={updateFilter}/>
</MobileFilterSection>
{/* WANTS KIDS */}
<MobileFilterSection
title="Wants kids"
@@ -206,6 +235,8 @@ function MobileFilters(props: {
<HasKidsFilter filters={filters} updateFilter={updateFilter}/>
</MobileFilterSection>
</>}
{/* Short Bios */}
<Col className="p-4 pb-2">
<ShortBioToggle

View File

@@ -15,7 +15,7 @@ export function PrefGenderFilterText(props: {
if (!pref_gender || pref_gender.length < 1) {
return (
<span>
<span className="hidden sm:inline">Interested in </span>
<span className="hidden sm:inline">Gender they seek: </span>
<span
className={clsx(
'text-semibold capitalize sm:normal-case',
@@ -29,7 +29,7 @@ export function PrefGenderFilterText(props: {
}
return (
<Row className="items-center gap-0.5 font-semibold">
<span className="hidden sm:inline">Interested in </span>
<span className="hidden sm:inline">Gender they seek: </span>
{pref_gender.map((gender) => {
return (
<GenderIcon

View File

@@ -0,0 +1,61 @@
import clsx from 'clsx'
import {convertRomanticTypes, RomanticType,} from 'web/lib/util/convert-relationship-type'
import stringOrStringArrayToText from 'web/lib/util/string-or-string-array-to-text'
import {MultiCheckbox} from 'web/components/multi-checkbox'
import {ROMANTIC_CHOICES} from "web/components/filters/choices";
import {FilterFields} from "common/filters";
export function RomanticFilterText(props: {
relationship: RomanticType[] | undefined
highlightedClass?: string
}) {
const {relationship, highlightedClass} = props
const length = (relationship ?? []).length
if (!relationship || length < 1) {
return (
<span className={clsx('text-semibold', highlightedClass)}>Any relationship</span>
)
}
const convertedTypes = relationship.map((r) =>
convertRomanticTypes(r)
)
if (length > 1) {
return (
<span>
<span className={clsx('font-semibold', highlightedClass)}>
Multiple
</span>
</span>
)
}
return (
<div>
<span className={clsx('font-semibold', highlightedClass)}>
{stringOrStringArrayToText({
text: convertedTypes,
capitalizeFirstLetterOption: true,
})}{' '}
</span>
</div>
)
}
export function RomanticFilter(props: {
filters: Partial<FilterFields>
updateFilter: (newState: Partial<FilterFields>) => void
}) {
const {filters, updateFilter} = props
return (
<MultiCheckbox
selected={filters.pref_romantic_styles ?? []}
choices={ROMANTIC_CHOICES as any}
onChange={(c) => {
updateFilter({pref_romantic_styles: c})
}}
/>
)
}

View File

@@ -133,6 +133,7 @@ export const Search = (props: {
const [openBookmarks, setOpenBookmarks] = useState(false);
const [openStarBookmarks, setOpenStarBookmarks] = useState(false);
const user = useUser()
const youSeekingRelationship = youProfile?.pref_relation_styles?.includes('relationship')
useEffect(() => {
if (isHolding) return;
@@ -216,6 +217,7 @@ export const Search = (props: {
setYourFilters={setYourFilters}
isYourFilters={isYourFilters}
locationFilterProps={locationFilterProps}
includeRelationshipFilters={youSeekingRelationship}
/>
</Row>
<RightModal
@@ -231,6 +233,7 @@ export const Search = (props: {
setYourFilters={setYourFilters}
isYourFilters={isYourFilters}
locationFilterProps={locationFilterProps}
includeRelationshipFilters={youSeekingRelationship}
/>
</RightModal>
<Row className={'mb-2 gap-2'}>

View File

@@ -83,6 +83,7 @@ export const useFilters = (you: Profile | undefined) => {
pref_age_max: (you?.pref_age_max ?? MAX_INT) < 100 ? you?.pref_age_max : undefined,
pref_age_min: (you?.pref_age_min ?? MIN_INT) > 18 ? you?.pref_age_min : undefined,
pref_relation_styles: you?.pref_relation_styles.length ? you.pref_relation_styles : undefined,
pref_romantic_styles: you?.pref_romantic_styles?.length ? you.pref_romantic_styles : undefined,
wants_kids_strength: wantsKidsDatabaseToWantsKidsFilter(
(you?.wants_kids_strength ?? 2) as wantsKidsDatabase
),
@@ -96,10 +97,9 @@ export const useFilters = (you: Profile | undefined) => {
!!you &&
(!location || location.id === you.geodb_city_id) &&
isEqual(filters.genders?.length ? filters.genders : undefined, yourFilters.genders?.length ? yourFilters.genders : undefined) &&
// isEqual(filters.pref_gender?.length ? filters.pref_gender[0] : undefined, you.gender) &&
// you?.pref_gender.length &&
// filters.pref_gender.length == 1 &&
// filters.pref_gender[0] == you.gender &&
filters.pref_gender?.length == 1 && isEqual(filters.pref_gender?.length ? filters.pref_gender[0] : undefined, you.gender) &&
isEqual(new Set(filters.pref_romantic_styles), new Set(you.pref_romantic_styles)) &&
isEqual(new Set(filters.pref_relation_styles), new Set(you.pref_relation_styles)) &&
filters.pref_age_max == yourFilters.pref_age_max &&
filters.pref_age_min == yourFilters.pref_age_min &&
filters.wants_kids_strength == yourFilters.wants_kids_strength

View File

@@ -1,7 +1,12 @@
import {REVERTED_RELATIONSHIP_CHOICES} from "web/components/filters/choices";
import {REVERTED_RELATIONSHIP_CHOICES, REVERTED_ROMANTIC_CHOICES} from "web/components/filters/choices";
export type RelationshipType = keyof typeof REVERTED_RELATIONSHIP_CHOICES
export type RomanticType = keyof typeof REVERTED_ROMANTIC_CHOICES
export function convertRelationshipType(relationshipType: RelationshipType) {
return REVERTED_RELATIONSHIP_CHOICES[relationshipType]
}
export function convertRomanticTypes(romanticType: RomanticType) {
return REVERTED_ROMANTIC_CHOICES[romanticType]
}