Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions src/components/modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -106,19 +106,19 @@ export default function Modal({
aria-labelledby={typeof title === 'string' ? title : 'modal-title'}
aria-modal="true"
onClick={() => closeOnBackdropClick && onClose()}
className="modal modal-middle flex items-center justify-center transition-opacity duration-200 opacity-100 p-2 md:p-4"
className="flex items-center justify-center p-2 transition-opacity duration-200 opacity-100 modal modal-middle md:p-4"
>
<div
ref={modalRef}
onClick={(e) => e.stopPropagation()}
className={`${modalBoxClasses} animate-modal-in`}
>
{(title || showCloseButton) && (
<div className="flex items-center justify-between mb-2 md:mb-3 gap-2 md:gap-4">
<div className="flex items-center justify-between gap-2 mb-2 md:mb-3 md:gap-4">
{title && (
<h3
id="modal-title"
className="text-base md:text-lg font-semibold"
className="text-base font-semibold md:text-lg"
>
{title}
</h3>
Expand Down
4 changes: 2 additions & 2 deletions src/components/section-panel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,11 @@ export function SectionPanel({ title, children, size = 'md', icon }: SectionPane
return (
<div className={`overflow-hidden ${sizeStyles.container} duration-300`}>
<div className={`${sizeStyles.header} border-b border-content`}>
<div className="flex items-center justify-between gap-2">
<div className="flex items-center gap-2">
{icon && React.cloneElement(icon, {})}
<h3 className={`font-medium ${sizeStyles.title} text-content`}>
{title}
</h3>
{icon && React.cloneElement(icon, {})}
</div>
</div>
<div className={sizeStyles.content}>{children}</div>
Expand Down
2 changes: 1 addition & 1 deletion src/components/tab-manager.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ export const TabManager = ({
const headClass =
tabPosition === 'top'
? 'flex-col gap-1 h-[80vh]'
: 'flex-col md:flex-row gap-4 h-[60vh]'
: 'flex-col md:flex-row gap-4 h-[80vh]'
const contentClass =
tabPosition === 'top'
? 'shrink-0 md:overflow-y-auto w-full'
Expand Down
2 changes: 1 addition & 1 deletion src/layouts/navbar/navbar.layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ export function NavbarLayout(): JSX.Element {
: '-bottom-32 opacity-0 scale-95 pointer-events-none'
}`}
>
<nav className="relative flex items-center gap-1 p-1.5 bg-white/[0.02] backdrop-blur-md border border-white/[0.08] rounded-[2.5rem]">
<nav className="relative flex items-center gap-1 p-1.5 bg-white/[0.02] backdrop-blur-sm border border-white/[0.08] rounded-[2.5rem]">
<button
onClick={() => onToggleNavbar()}
className="relative z-10 p-2 transition-colors cursor-pointer text-white/20 hover:text-white/40"
Expand Down
92 changes: 92 additions & 0 deletions src/layouts/setting/tabs/account/components/interests-selector.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import { useState, useRef } from 'react'
import { ClickableTooltip } from '@/components/clickableTooltip'
import type { ProfileMetaItem } from '@/services/hooks/profile/getProfileMeta.hook'

interface InterestsSelectorProps {
interests: ProfileMetaItem[]
selectedInterests: string[]
onSelect: (interestIds: string[]) => void
isLoading?: boolean
triggerElement: React.ReactNode
}

export const InterestsSelector = ({
interests,
selectedInterests,
onSelect,
isLoading = false,
triggerElement,
}: InterestsSelectorProps) => {
const [isOpen, setIsOpen] = useState(false)
const triggerRef = useRef<HTMLButtonElement>(null)

const handleInterestToggle = (interestId: string) => {
const isSelected = selectedInterests.includes(interestId)
if (isSelected) {
onSelect(selectedInterests.filter((id) => id !== interestId))
} else if (selectedInterests.length < 3) {
onSelect([...selectedInterests, interestId])
}
}

const content = (
<div className="w-48 p-1 overflow-x-hidden overflow-y-auto scrollbar-none max-h-40">
{isLoading ? (
<div className="py-4 text-center text-[10px] font-black italic animate-pulse">
صبر کنید...
</div>
) : (
<div className="flex flex-row flex-wrap gap-1">
{interests.map((interest) => {
const isSelected = selectedInterests.includes(interest.id)
const canSelect = selectedInterests.length < 3 || isSelected

return (
<button
key={interest.id}
type="button"
disabled={!canSelect}
onClick={() => handleInterestToggle(interest.id)}
className={`
h-8 px-3 w-fit flex items-center justify-center
text-[10px] font-black italic rounded-full text-muted border
transition-all duration-200 active:scale-95 cursor-pointer
${
isSelected
? 'bg-primary border-primary text-white! shadow-md shadow-primary/20'
: !canSelect
? 'opacity-30 cursor-not-allowed border-base-300'
: 'bg-base-200/50 border-base-300/30 text-content/70 hover:bg-base-200'
}
`}
>
{interest.title}
</button>
)
})}
</div>
)}
</div>
)

return (
<>
<button
ref={triggerRef}
type="button"
onClick={() => setIsOpen(!isOpen)}
className="flex items-center justify-between w-full p-3 text-right transition-colors hover:bg-content"
>
{triggerElement}
</button>

<ClickableTooltip
content={content}
triggerRef={triggerRef}
isOpen={isOpen}
setIsOpen={setIsOpen}
position="bottom"
/>
</>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import { useState, useRef } from 'react'
import { ClickableTooltip } from '@/components/clickableTooltip'
import type { ProfileMetaItem } from '@/services/hooks/profile/getProfileMeta.hook'

interface OccupationSelectorProps {
occupations: ProfileMetaItem[]
selectedOccupation: string | null
onSelect: (occupationId: string | null) => void
isLoading?: boolean
triggerElement: React.ReactNode
}

export const OccupationSelector = ({
occupations,
selectedOccupation,
onSelect,
isLoading = false,
triggerElement,
}: OccupationSelectorProps) => {
const [isOpen, setIsOpen] = useState(false)
const triggerRef = useRef<HTMLButtonElement>(null)

const handleSelect = (occupationId: string) => {
if (selectedOccupation === occupationId) {
onSelect(null)
} else {
onSelect(occupationId)
}
setIsOpen(false)
}

const content = (
<div className="w-48 p-1 overflow-x-hidden overflow-y-auto scrollbar-none max-h-40">
{isLoading ? (
<div className="py-4 text-center text-[10px] font-black italic animate-pulse">
درحال بارگذاری...
</div>
) : (
<div className="flex flex-row flex-wrap gap-1">
{occupations.map((occupation) => {
const isActive = selectedOccupation === occupation.id
return (
<button
key={occupation.id}
type="button"
onClick={() => handleSelect(occupation.id)}
className={`
h-8 px-3 w-fit flex items-center justify-center
text-[10px] font-black italic rounded-full text-muted border
transition-all duration-200 active:scale-95 cursor-pointer
${
isActive
? 'bg-primary border-primary shadow-sm text-white!'
: 'bg-base-200/50 border-base-300/30 text-content hover:bg-base-200'
}
`}
>
{occupation.title}
</button>
)
})}
</div>
)}
</div>
)

return (
<>
<button
ref={triggerRef}
type="button"
onClick={() => setIsOpen(!isOpen)}
className="flex items-center justify-between w-full p-3 text-right transition-colors hover:bg-content"
>
{triggerElement}
</button>

<ClickableTooltip
content={content}
triggerRef={triggerRef}
isOpen={isOpen}
setIsOpen={setIsOpen}
position="bottom"
className=""
/>
</>
)
}
Loading