mirror of
https://github.com/CompassConnections/Compass.git
synced 2026-05-14 01:54:40 -04:00
Add filter: religion
This commit is contained in:
@@ -22,6 +22,7 @@ export type profileQueryType = {
|
||||
pref_romantic_styles?: String[] | undefined,
|
||||
diet?: String[] | undefined,
|
||||
political_beliefs?: String[] | undefined,
|
||||
religion?: String[] | undefined,
|
||||
wants_kids_strength?: number | undefined,
|
||||
has_kids?: number | undefined,
|
||||
is_smoker?: boolean | undefined,
|
||||
@@ -57,6 +58,7 @@ export const loadProfiles = async (props: profileQueryType) => {
|
||||
pref_romantic_styles,
|
||||
diet,
|
||||
political_beliefs,
|
||||
religion,
|
||||
wants_kids_strength,
|
||||
has_kids,
|
||||
is_smoker,
|
||||
@@ -102,6 +104,8 @@ export const loadProfiles = async (props: profileQueryType) => {
|
||||
intersection(diet, l.diet).length) &&
|
||||
(!political_beliefs ||
|
||||
intersection(political_beliefs, l.political_beliefs).length) &&
|
||||
(!religion ||
|
||||
intersection(religion, l.religion).length) &&
|
||||
(!wants_kids_strength ||
|
||||
wants_kids_strength == -1 ||
|
||||
!l.wants_kids_strength ||
|
||||
@@ -199,6 +203,12 @@ export const loadProfiles = async (props: profileQueryType) => {
|
||||
{political_beliefs}
|
||||
),
|
||||
|
||||
religion?.length &&
|
||||
where(
|
||||
`religion IS NULL OR religion = '{}' OR religion && $(religion)`,
|
||||
{religion}
|
||||
),
|
||||
|
||||
!!wants_kids_strength &&
|
||||
wants_kids_strength !== -1 &&
|
||||
where(
|
||||
|
||||
@@ -402,6 +402,7 @@ export const API = (_apiTypeCheck = {
|
||||
pref_age_max: z.coerce.number().optional(),
|
||||
drinks_min: z.coerce.number().optional(),
|
||||
drinks_max: z.coerce.number().optional(),
|
||||
religion: arraybeSchema.optional(),
|
||||
pref_relation_styles: arraybeSchema.optional(),
|
||||
pref_romantic_styles: arraybeSchema.optional(),
|
||||
diet: arraybeSchema.optional(),
|
||||
|
||||
@@ -77,6 +77,7 @@ const optionalProfilesSchema = z.object({
|
||||
political_beliefs: z.array(z.string()).optional(),
|
||||
religious_belief_strength: z.number().optional(),
|
||||
religious_beliefs: z.string().optional(),
|
||||
religion: z.array(z.string()).optional(),
|
||||
ethnicity: z.array(z.string()).optional(),
|
||||
born_in_location: z.string().optional(),
|
||||
height_in_inches: z.number().optional(),
|
||||
|
||||
@@ -32,6 +32,7 @@ export type FilterFields = {
|
||||
| 'pref_gender'
|
||||
| 'pref_age_min'
|
||||
| 'pref_age_max'
|
||||
| 'religion'
|
||||
>
|
||||
|
||||
export const orderProfiles = (
|
||||
@@ -70,6 +71,7 @@ export const initialFilters: Partial<FilterFields> = {
|
||||
pref_romantic_styles: undefined,
|
||||
diet: undefined,
|
||||
political_beliefs: undefined,
|
||||
religion: undefined,
|
||||
pref_gender: undefined,
|
||||
shortBio: undefined,
|
||||
drinks_min: undefined,
|
||||
|
||||
@@ -17,6 +17,7 @@ const filterLabels: Record<string, string> = {
|
||||
wants_kids_strength: "Kids",
|
||||
is_smoker: "",
|
||||
pref_relation_styles: "Seeking",
|
||||
religion: "",
|
||||
pref_gender: "",
|
||||
orderBy: "",
|
||||
diet: "Diet",
|
||||
|
||||
20
common/src/util/sorting.ts
Normal file
20
common/src/util/sorting.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
import {MAX_INT} from "common/constants";
|
||||
|
||||
export function getSortedOptions(options: string[], order: string[] | Record<string, string>) {
|
||||
let parsedOrder: string[]
|
||||
if (Array.isArray(order)) {
|
||||
parsedOrder = order
|
||||
} else {
|
||||
parsedOrder = Object.keys(order)
|
||||
}
|
||||
return options
|
||||
.slice()
|
||||
.sort((a, b) => {
|
||||
const ia = parsedOrder.indexOf(a as any)
|
||||
const ib = parsedOrder.indexOf(b as any)
|
||||
const sa = ia === -1 ? MAX_INT : ia
|
||||
const sb = ib === -1 ? MAX_INT : ib
|
||||
if (sa !== sb) return sa - sb
|
||||
return String(a).localeCompare(String(b))
|
||||
});
|
||||
}
|
||||
@@ -26,11 +26,12 @@ import {PoliticalFilter, PoliticalFilterText} from "web/components/filters/polit
|
||||
import {GiFruitBowl} from "react-icons/gi";
|
||||
import {RiScales3Line} from "react-icons/ri";
|
||||
import {EducationFilter, EducationFilterText} from "web/components/filters/education-filter";
|
||||
import {LuGraduationCap} from "react-icons/lu";
|
||||
import {LuCigarette, LuGraduationCap} from "react-icons/lu";
|
||||
import {DrinksFilter, DrinksFilterText} from "web/components/filters/drinks-filter";
|
||||
import {MdLocalBar} from 'react-icons/md'
|
||||
import {SmokerFilter, SmokerFilterText} from 'web/components/filters/smoker-filter'
|
||||
import {LuCigarette} from 'react-icons/lu'
|
||||
import {SmokerFilter, SmokerFilterText} from "web/components/filters/smoker-filter"
|
||||
import {ReligionFilter, ReligionFilterText} from "web/components/filters/religion-filter";
|
||||
import {PiHandsPrayingBold} from "react-icons/pi";
|
||||
|
||||
export function DesktopFilters(props: {
|
||||
filters: Partial<FilterFields>
|
||||
@@ -381,6 +382,33 @@ export function DesktopFilters(props: {
|
||||
menuWidth="w-50"
|
||||
/>
|
||||
|
||||
{/* RELIGION */}
|
||||
<CustomizeableDropdown
|
||||
buttonContent={(open) => (
|
||||
<DropdownButton
|
||||
open={open}
|
||||
content={
|
||||
<Row className="items-center gap-1">
|
||||
<PiHandsPrayingBold className="h-4 w-4"/>
|
||||
<ReligionFilterText
|
||||
options={
|
||||
filters.religion as
|
||||
| string[]
|
||||
| undefined
|
||||
}
|
||||
highlightedClass={open ? 'text-primary-500' : undefined}
|
||||
/>
|
||||
</Row>
|
||||
}
|
||||
/>
|
||||
)}
|
||||
dropdownMenuContent={
|
||||
<ReligionFilter filters={filters} updateFilter={updateFilter}/>
|
||||
}
|
||||
popoverClassName="bg-canvas-50"
|
||||
menuWidth="w-50"
|
||||
/>
|
||||
|
||||
{/* SMOKER */}
|
||||
<CustomizeableDropdown
|
||||
buttonContent={(open) => (
|
||||
@@ -399,7 +427,7 @@ export function DesktopFilters(props: {
|
||||
)}
|
||||
dropdownMenuContent={
|
||||
<Col className="mx-2 mb-4">
|
||||
<SmokerFilter filters={filters} updateFilter={updateFilter} />
|
||||
<SmokerFilter filters={filters} updateFilter={updateFilter}/>
|
||||
</Col>
|
||||
}
|
||||
popoverClassName="bg-canvas-50"
|
||||
|
||||
@@ -5,7 +5,7 @@ import {FilterFields} from "common/filters";
|
||||
import {EDUCATION_CHOICES} from "web/components/filters/choices";
|
||||
import {convertEducationTypes} from "web/lib/util/convert-types";
|
||||
import stringOrStringArrayToText from "web/lib/util/string-or-string-array-to-text";
|
||||
import {MAX_INT} from "common/constants";
|
||||
import {getSortedOptions} from "common/util/sorting";
|
||||
|
||||
export function EducationFilterText(props: {
|
||||
options: string[] | undefined
|
||||
@@ -20,20 +20,9 @@ export function EducationFilterText(props: {
|
||||
)
|
||||
}
|
||||
|
||||
const order = Object.values(EDUCATION_CHOICES)
|
||||
const sortedOptions = options
|
||||
.slice()
|
||||
.sort((a, b) => {
|
||||
const ia = order.indexOf(a as any)
|
||||
const ib = order.indexOf(b as any)
|
||||
const sa = ia === -1 ? MAX_INT : ia
|
||||
const sb = ib === -1 ? MAX_INT : ib
|
||||
if (sa !== sb) return sa - sb
|
||||
return String(a).localeCompare(String(b))
|
||||
})
|
||||
|
||||
const sortedOptions = getSortedOptions(options, EDUCATION_CHOICES)
|
||||
const convertedTypes = sortedOptions.map((r) => convertEducationTypes(r as any))
|
||||
|
||||
|
||||
return (
|
||||
<div>
|
||||
<span className={clsx('font-semibold', highlightedClass)}>
|
||||
|
||||
@@ -24,6 +24,7 @@ import {PoliticalFilter, PoliticalFilterText} from "web/components/filters/polit
|
||||
import {EducationFilter, EducationFilterText} from "web/components/filters/education-filter";
|
||||
import {DrinksFilter, DrinksFilterText, getNoMinMaxDrinks} from "./drinks-filter";
|
||||
import {SmokerFilter, SmokerFilterText} from "./smoker-filter";
|
||||
import {ReligionFilter, ReligionFilterText} from "web/components/filters/religion-filter";
|
||||
|
||||
function MobileFilters(props: {
|
||||
filters: Partial<FilterFields>
|
||||
@@ -329,6 +330,24 @@ function MobileFilters(props: {
|
||||
<PoliticalFilter filters={filters} updateFilter={updateFilter}/>
|
||||
</MobileFilterSection>
|
||||
|
||||
{/* RELIGION */}
|
||||
<MobileFilterSection
|
||||
title="Religion"
|
||||
openFilter={openFilter}
|
||||
setOpenFilter={setOpenFilter}
|
||||
isActive={hasAny(filters.religion || undefined)}
|
||||
selection={
|
||||
<ReligionFilterText
|
||||
options={filters.religion as string[]}
|
||||
highlightedClass={
|
||||
hasAny(filters.religion || undefined) ? 'text-primary-600' : 'text-ink-900'
|
||||
}
|
||||
/>
|
||||
}
|
||||
>
|
||||
<ReligionFilter filters={filters} updateFilter={updateFilter}/>
|
||||
</MobileFilterSection>
|
||||
|
||||
{/* EDUCATION */}
|
||||
<MobileFilterSection
|
||||
title="Education"
|
||||
|
||||
55
web/components/filters/religion-filter.tsx
Normal file
55
web/components/filters/religion-filter.tsx
Normal file
@@ -0,0 +1,55 @@
|
||||
import clsx from 'clsx'
|
||||
import {MultiCheckbox} from 'web/components/multi-checkbox'
|
||||
|
||||
import {FilterFields} from "common/filters";
|
||||
import {RELIGION_CHOICES} from "web/components/filters/choices";
|
||||
import {convertReligionTypes} from "web/lib/util/convert-types";
|
||||
import stringOrStringArrayToText from "web/lib/util/string-or-string-array-to-text";
|
||||
import {getSortedOptions} from "common/util/sorting";
|
||||
|
||||
|
||||
export function ReligionFilterText(props: {
|
||||
options: string[] | undefined
|
||||
highlightedClass?: string
|
||||
}) {
|
||||
const {options, highlightedClass} = props
|
||||
const length = (options ?? []).length
|
||||
|
||||
if (!options || length < 1) {
|
||||
return (
|
||||
<span className={clsx('text-semibold', highlightedClass)}>Any religion</span>
|
||||
)
|
||||
}
|
||||
|
||||
const sortedOptions = getSortedOptions(options, RELIGION_CHOICES)
|
||||
const convertedTypes = sortedOptions.map((r) => convertReligionTypes(r as any))
|
||||
|
||||
return (
|
||||
<div>
|
||||
<span className={clsx('font-semibold', highlightedClass)}>
|
||||
{stringOrStringArrayToText({
|
||||
text: convertedTypes,
|
||||
capitalizeFirstLetterOption: true,
|
||||
})}{' '}
|
||||
</span>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export function ReligionFilter(props: {
|
||||
filters: Partial<FilterFields>
|
||||
updateFilter: (newState: Partial<FilterFields>) => void
|
||||
}) {
|
||||
const {filters, updateFilter} = props
|
||||
return (
|
||||
<>
|
||||
<MultiCheckbox
|
||||
selected={filters.religion ?? []}
|
||||
choices={RELIGION_CHOICES}
|
||||
onChange={(c) => {
|
||||
updateFilter({religion: c})
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
)
|
||||
}
|
||||
@@ -73,6 +73,7 @@ export const useFilters = (you: Profile | undefined) => {
|
||||
pref_romantic_styles: you?.pref_romantic_styles?.length ? you.pref_romantic_styles : undefined,
|
||||
diet: you?.diet?.length ? you.diet : undefined,
|
||||
political_beliefs: you?.political_beliefs?.length ? you.political_beliefs : undefined,
|
||||
religion: you?.religion?.length ? you.religion : undefined,
|
||||
wants_kids_strength: wantsKidsDatabaseToWantsKidsFilter(
|
||||
(you?.wants_kids_strength ?? 2) as wantsKidsDatabase
|
||||
),
|
||||
@@ -93,6 +94,7 @@ export const useFilters = (you: Profile | undefined) => {
|
||||
&& isEqual(new Set(filters.pref_relation_styles), new Set(you.pref_relation_styles))
|
||||
&& isEqual(new Set(filters.diet), new Set(you.diet))
|
||||
&& isEqual(new Set(filters.political_beliefs), new Set(you.political_beliefs))
|
||||
&& isEqual(new Set(filters.religion), new Set(you.religion))
|
||||
&& filters.pref_age_max == yourFilters.pref_age_max
|
||||
&& filters.pref_age_min == yourFilters.pref_age_min
|
||||
&& filters.wants_kids_strength == yourFilters.wants_kids_strength
|
||||
|
||||
Reference in New Issue
Block a user