Skip to content

Commit

Permalink
Merge pull request #119 from BacPacNet/group-category
Browse files Browse the repository at this point in the history
Group category
  • Loading branch information
bacpactech authored Dec 10, 2024
2 parents 0b84c0a + c301bfb commit 8e4c19d
Show file tree
Hide file tree
Showing 15 changed files with 831 additions and 625 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ const AssignGroupModerators = ({ setAssignUsers, assignUsers, id, isGroup }: Pro
const { data: communityUsers } = useGetCommunityUsers(id, !isGroup, 'Private', searchInput)
const { mutate: userGroupRole } = useUserGroupRole()
const { mutate: userCommunityRole } = useUserCommunityRole()

const handleChange = (e: any, communityGroupId: string, postId: string, item: any) => {
if (!isGroup) {
const data = {
Expand Down
132 changes: 132 additions & 0 deletions src/components/molecules/CommunityGroupFilter/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
'use client'
import Buttons from '@/components/atoms/Buttons'
import { useGetFilteredSubscribedCommunities } from '@/services/university-community'
import { subCategories } from '@/types/CommuityGroup'
import React, { useEffect, useState } from 'react'
import { RiDeleteBin6Line } from 'react-icons/ri'

const GroupCategories = ['Private', 'Public', 'Official', 'Casual']

type Props = {
communityId: string
selectedFiltersMain: Record<string, string[]>
setSelectedFiltersMain: React.Dispatch<React.SetStateAction<Record<string, string[]>>>
selectedTypeMain: string[]
setSelectedTypeMain: React.Dispatch<React.SetStateAction<string[]>>
}

const CommunityGroupFilterComponent: React.FC<Props> = ({
communityId,
setSelectedFiltersMain,
selectedFiltersMain,
setSelectedTypeMain,
selectedTypeMain,
}) => {
const [selectedFilters, setSelectedFilters] = useState<Record<string, string[]>>({})
const [selectedType, setSelectedType] = useState<string[]>([])
const { mutate } = useGetFilteredSubscribedCommunities(communityId)

const handleSelect = (category: string, option: string) => {
setSelectedFilters((prev: any) => {
const categoryFilters = prev[category] || []
if (categoryFilters.includes(option)) {
const updatedFilters = categoryFilters.filter((item: any) => item !== option)
if (updatedFilters.length === 0) {
const { [category]: _, ...rest } = prev
return rest
}
return {
...prev,
[category]: updatedFilters,
}
} else {
return {
...prev,
[category]: [...categoryFilters, option],
}
}
})
}

const handleSelectTypes = (type: string) => {
setSelectedType((prev) => (prev.includes(type) ? prev.filter((item) => item !== type) : [...prev, type]))
}

const clearFilters = () => {
setSelectedFilters({})
setSelectedType([])
}

const handleClick = () => {
const data = { selectedType, selectedFilters }
setSelectedFiltersMain(selectedFilters)
setSelectedTypeMain(selectedType)
mutate(data)
}

useEffect(() => {
if (selectedFiltersMain) {
setSelectedFilters(selectedFiltersMain)
}
if (selectedTypeMain) {
setSelectedType(selectedTypeMain)
}
}, [])
return (
<div className="max-w-md mx-auto flex flex-col justify-center ">
<div className="flex justify-between items-center mb-4">
<h2 className="text-lg font-semibold">Filter</h2>
<button onClick={clearFilters} className=" text-2xs flex items-center gap-1 border border-neutral-200 shadow-sm px-3 py-2 rounded-lg">
<span className="flex items-center gap-2">
Clear <RiDeleteBin6Line />
</span>
</button>
</div>

<div className="mb-6">
<h3 className="font-medium text-sm mb-2">Group Access & Type</h3>
<div className="flex flex-wrap gap-2">
{GroupCategories.map((option) => (
<button
key={option}
onClick={() => handleSelectTypes(option)}
className={`px-2 py-1 text-2xs border border-neutral-200 rounded-3xl ${
selectedType?.includes(option) ? 'bg-primary text-white border-primary-500' : ' text-neutral-700 border-neutral-300'
}`}
>
{option}
</button>
))}
</div>
</div>

{Object.entries(subCategories).map(([category, options]) => {
if (category == 'Others') return
return (
<div key={category} className="mb-6">
<h3 className="font-medium text-sm mb-2">{category}</h3>
<div className="flex flex-wrap gap-2">
{options.map((option) => (
<button
key={option}
onClick={() => handleSelect(category, option)}
className={`px-2 py-1 text-2xs border border-neutral-200 rounded-3xl ${
selectedFilters[category]?.includes(option) ? 'bg-primary text-white border-primary-500' : ' text-neutral-700 border-neutral-300'
}`}
>
{option}
</button>
))}
</div>
</div>
)
})}

<Buttons onClick={() => handleClick()} className="w-max self-center" size="extra_small" variant="primary">
Apply Filters
</Buttons>
</div>
)
}

export default CommunityGroupFilterComponent
61 changes: 21 additions & 40 deletions src/components/molecules/CreateNewGroupBox/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import Buttons from '@/components/atoms/Buttons'
import SelectUsers from '@/components/atoms/SelectUsers'
import { IoClose } from 'react-icons/io5'
import { useUniStore } from '@/store/store'
import { categories, Category, subCategories } from '@/types/CommuityGroup'

type Props = {
communityId: string
Expand All @@ -26,39 +27,7 @@ type user = {
major: string
}

type Category = 'Academic Focus' | 'Recreation and Hobbies' | 'Advocacy and Awareness' | 'Personal Growth' | 'Professional Development' | 'Others'

const subCategories: Record<Category, string[]> = {
'Academic Focus': [
'Science & Technology',
'Arts & Humanities',
'Social Sciences',
'Education',
'Business & Economics',
'Health & Medicine',
'Environmental Studies',
'Law & Policy',
'Mathematics & Statistics',
'Engineering',
],
'Recreation and Hobbies': ['f', 'g', 'h'],
'Advocacy and Awareness': ['i', 'j'],
'Personal Growth': ['k', 'l', 'm'],
'Professional Development': ['n', 'o'],
Others: [],
}

const categories: Category[] = [
'Academic Focus',
'Recreation and Hobbies',
'Advocacy and Awareness',
'Personal Growth',
'Professional Development',
'Others',
]

const CreateNewGroup = ({ setNewGroup, communityId }: Props) => {
const { userProfileData } = useUniStore()
const [logoImage, setLogoImage] = useState()
const [coverImage, setCoverImage] = useState()
const [isLoading, setIsLoading] = useState(false)
Expand All @@ -75,6 +44,7 @@ const CreateNewGroup = ({ setNewGroup, communityId }: Props) => {
handleSubmit: handleGroupCreate,
formState: { errors: GroupErrors },
getValues,
setError,
} = useForm()

const handleSelectAll = useCallback(() => {
Expand Down Expand Up @@ -103,14 +73,23 @@ const CreateNewGroup = ({ setNewGroup, communityId }: Props) => {
const imagedata: any = await replaceImage(logoImage, '')
logoImageData = { communityGroupLogoUrl: { imageUrl: imagedata?.imageUrl, publicId: imagedata?.publicId } }
}

if (selectedGroupCategory !== 'Others' && groupSubCategory.length < 1) {
setIsLoading(false)
return setError('groupCategory', { type: 'manual', message: 'Sub category required!' })
}
const selectedUsersId = selectedUsers.map((item) => item.id)
const dataToPush = {
...data,
...CoverImageData,
...logoImageData,
selectedUsersId,
selectedGroupCategory,
groupSubCategory,
}

// return console.log('push', dataToPush)

createGroup({ communityId: communityId, data: dataToPush })
setIsLoading(false)
setNewGroup(false)
Expand Down Expand Up @@ -189,43 +168,43 @@ const CreateNewGroup = ({ setNewGroup, communityId }: Props) => {
<div>
<h2 className="font-medium text-xs">Group Access</h2>
<label className="flex items-center gap-3">
<input type="radio" value="Public" {...GroupRegister('communityGroupType', { required: true })} className="w-5 h-5" />
<input type="radio" value="Public" {...GroupRegister('communityGroupAccess', { required: true })} className="w-5 h-5" />
<div className="py-2">
<span className="text-neutral-900 text-[12px] font-medium">Public</span>
<p className="text-neutral-400 text-[12px] ">Anyone can join</p>
</div>
</label>

<label className="flex items-center gap-3">
<input type="radio" value="Private" {...GroupRegister('communityGroupType', { required: true })} className="w-5 h-5" />
<input type="radio" value="Private" {...GroupRegister('communityGroupAccess', { required: true })} className="w-5 h-5" />
<div>
<span className="text-neutral-900 text-[12px] font-medium">Private</span>
<p className="text-neutral-400 text-[12px] ">Permission to join required</p>
</div>
</label>
{GroupErrors.communityGroupType && <p className="text-red-500 text-2xs">This field is required</p>}
{GroupErrors.communityGroupAccess && <p className="text-red-500 text-2xs">This field is required</p>}
</div>

{/* communty group type */}

<div>
<h2 className="font-medium text-xs">Group Type</h2>
<label className="flex items-center gap-3">
<input type="radio" value="Casual" {...GroupRegister('groupType', { required: true })} className="w-5 h-5" />
<input type="radio" value="Casual" {...GroupRegister('communityGroupType', { required: true })} className="w-5 h-5" />
<div className="py-2">
<span className="text-neutral-900 text-[12px] font-medium">Casual</span>
<p className="text-neutral-400 text-[12px] ">No approval required</p>
</div>
</label>

<label className="flex items-center gap-3">
<input type="radio" value="Official" {...GroupRegister('groupType', { required: true })} className="w-5 h-5" />
<input type="radio" value="Official" {...GroupRegister('communityGroupType', { required: true })} className="w-5 h-5" />
<div>
<span className="text-neutral-900 text-[12px] font-medium">Official</span>
<p className="text-neutral-400 text-[12px] ">Require university approval</p>
</div>
</label>
{GroupErrors.groupType && <p className="text-red-500 text-2xs ">This field is required</p>}
{GroupErrors.communityGroupType && <p className="text-red-500 text-2xs ">This field is required</p>}
</div>

{/* Repost setting */}
Expand Down Expand Up @@ -282,7 +261,9 @@ const CreateNewGroup = ({ setNewGroup, communityId }: Props) => {
</>
))}
</div>
{GroupErrors.groupCategory && <p className="text-red-500 text-2xs ">This field is required</p>}
{GroupErrors.groupCategory && (
<p className="text-red-500 text-2xs ">{GroupErrors.groupCategory.message?.toString() || 'This field is required'}</p>
)}
</div>
<div className="relative w-full flex flex-col">
<label htmlFor="inviteFriends" className="font-medium text-xs">
Expand Down Expand Up @@ -335,7 +316,7 @@ const CreateNewGroup = ({ setNewGroup, communityId }: Props) => {
)}
</div>
</div>
<button type="submit" className="bg-[#6647FF] py-2 rounded-lg text-white w-3/4 mx-auto">
<button disabled={isPending} type="submit" className="bg-[#6647FF] py-2 rounded-lg text-white w-3/4 mx-auto">
{isLoading || isPending ? <Spinner /> : <p>Create Group</p>}
</button>
{/* <button
Expand Down
Loading

0 comments on commit 8e4c19d

Please sign in to comment.