Skip to content

Commit b487110

Browse files
authored
Merge pull request #367 from widgetify-app/feature/profile-enhancements
Feature/profile enhancements
2 parents 698fd99 + 67c24ca commit b487110

11 files changed

Lines changed: 872 additions & 432 deletions

File tree

src/components/modal.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -106,19 +106,19 @@ export default function Modal({
106106
aria-labelledby={typeof title === 'string' ? title : 'modal-title'}
107107
aria-modal="true"
108108
onClick={() => closeOnBackdropClick && onClose()}
109-
className="modal modal-middle flex items-center justify-center transition-opacity duration-200 opacity-100 p-2 md:p-4"
109+
className="flex items-center justify-center p-2 transition-opacity duration-200 opacity-100 modal modal-middle md:p-4"
110110
>
111111
<div
112112
ref={modalRef}
113113
onClick={(e) => e.stopPropagation()}
114114
className={`${modalBoxClasses} animate-modal-in`}
115115
>
116116
{(title || showCloseButton) && (
117-
<div className="flex items-center justify-between mb-2 md:mb-3 gap-2 md:gap-4">
117+
<div className="flex items-center justify-between gap-2 mb-2 md:mb-3 md:gap-4">
118118
{title && (
119119
<h3
120120
id="modal-title"
121-
className="text-base md:text-lg font-semibold"
121+
className="text-base font-semibold md:text-lg"
122122
>
123123
{title}
124124
</h3>

src/components/section-panel.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,11 +47,11 @@ export function SectionPanel({ title, children, size = 'md', icon }: SectionPane
4747
return (
4848
<div className={`overflow-hidden ${sizeStyles.container} duration-300`}>
4949
<div className={`${sizeStyles.header} border-b border-content`}>
50-
<div className="flex items-center justify-between gap-2">
50+
<div className="flex items-center gap-2">
51+
{icon && React.cloneElement(icon, {})}
5152
<h3 className={`font-medium ${sizeStyles.title} text-content`}>
5253
{title}
5354
</h3>
54-
{icon && React.cloneElement(icon, {})}
5555
</div>
5656
</div>
5757
<div className={sizeStyles.content}>{children}</div>

src/components/tab-manager.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ export const TabManager = ({
6565
const headClass =
6666
tabPosition === 'top'
6767
? 'flex-col gap-1 h-[80vh]'
68-
: 'flex-col md:flex-row gap-4 h-[60vh]'
68+
: 'flex-col md:flex-row gap-4 h-[80vh]'
6969
const contentClass =
7070
tabPosition === 'top'
7171
? 'shrink-0 md:overflow-y-auto w-full'

src/layouts/navbar/navbar.layout.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ export function NavbarLayout(): JSX.Element {
123123
: '-bottom-32 opacity-0 scale-95 pointer-events-none'
124124
}`}
125125
>
126-
<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]">
126+
<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]">
127127
<button
128128
onClick={() => onToggleNavbar()}
129129
className="relative z-10 p-2 transition-colors cursor-pointer text-white/20 hover:text-white/40"
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
import { useState, useRef } from 'react'
2+
import { ClickableTooltip } from '@/components/clickableTooltip'
3+
import type { ProfileMetaItem } from '@/services/hooks/profile/getProfileMeta.hook'
4+
5+
interface InterestsSelectorProps {
6+
interests: ProfileMetaItem[]
7+
selectedInterests: string[]
8+
onSelect: (interestIds: string[]) => void
9+
isLoading?: boolean
10+
triggerElement: React.ReactNode
11+
}
12+
13+
export const InterestsSelector = ({
14+
interests,
15+
selectedInterests,
16+
onSelect,
17+
isLoading = false,
18+
triggerElement,
19+
}: InterestsSelectorProps) => {
20+
const [isOpen, setIsOpen] = useState(false)
21+
const triggerRef = useRef<HTMLButtonElement>(null)
22+
23+
const handleInterestToggle = (interestId: string) => {
24+
const isSelected = selectedInterests.includes(interestId)
25+
if (isSelected) {
26+
onSelect(selectedInterests.filter((id) => id !== interestId))
27+
} else if (selectedInterests.length < 3) {
28+
onSelect([...selectedInterests, interestId])
29+
}
30+
}
31+
32+
const content = (
33+
<div className="w-48 p-1 overflow-x-hidden overflow-y-auto scrollbar-none max-h-40">
34+
{isLoading ? (
35+
<div className="py-4 text-center text-[10px] font-black italic animate-pulse">
36+
صبر کنید...
37+
</div>
38+
) : (
39+
<div className="flex flex-row flex-wrap gap-1">
40+
{interests.map((interest) => {
41+
const isSelected = selectedInterests.includes(interest.id)
42+
const canSelect = selectedInterests.length < 3 || isSelected
43+
44+
return (
45+
<button
46+
key={interest.id}
47+
type="button"
48+
disabled={!canSelect}
49+
onClick={() => handleInterestToggle(interest.id)}
50+
className={`
51+
h-8 px-3 w-fit flex items-center justify-center
52+
text-[10px] font-black italic rounded-full text-muted border
53+
transition-all duration-200 active:scale-95 cursor-pointer
54+
${
55+
isSelected
56+
? 'bg-primary border-primary text-white! shadow-md shadow-primary/20'
57+
: !canSelect
58+
? 'opacity-30 cursor-not-allowed border-base-300'
59+
: 'bg-base-200/50 border-base-300/30 text-content/70 hover:bg-base-200'
60+
}
61+
`}
62+
>
63+
{interest.title}
64+
</button>
65+
)
66+
})}
67+
</div>
68+
)}
69+
</div>
70+
)
71+
72+
return (
73+
<>
74+
<button
75+
ref={triggerRef}
76+
type="button"
77+
onClick={() => setIsOpen(!isOpen)}
78+
className="flex items-center justify-between w-full p-3 text-right transition-colors hover:bg-content"
79+
>
80+
{triggerElement}
81+
</button>
82+
83+
<ClickableTooltip
84+
content={content}
85+
triggerRef={triggerRef}
86+
isOpen={isOpen}
87+
setIsOpen={setIsOpen}
88+
position="bottom"
89+
/>
90+
</>
91+
)
92+
}
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
import { useState, useRef } from 'react'
2+
import { ClickableTooltip } from '@/components/clickableTooltip'
3+
import type { ProfileMetaItem } from '@/services/hooks/profile/getProfileMeta.hook'
4+
5+
interface OccupationSelectorProps {
6+
occupations: ProfileMetaItem[]
7+
selectedOccupation: string | null
8+
onSelect: (occupationId: string | null) => void
9+
isLoading?: boolean
10+
triggerElement: React.ReactNode
11+
}
12+
13+
export const OccupationSelector = ({
14+
occupations,
15+
selectedOccupation,
16+
onSelect,
17+
isLoading = false,
18+
triggerElement,
19+
}: OccupationSelectorProps) => {
20+
const [isOpen, setIsOpen] = useState(false)
21+
const triggerRef = useRef<HTMLButtonElement>(null)
22+
23+
const handleSelect = (occupationId: string) => {
24+
if (selectedOccupation === occupationId) {
25+
onSelect(null)
26+
} else {
27+
onSelect(occupationId)
28+
}
29+
setIsOpen(false)
30+
}
31+
32+
const content = (
33+
<div className="w-48 p-1 overflow-x-hidden overflow-y-auto scrollbar-none max-h-40">
34+
{isLoading ? (
35+
<div className="py-4 text-center text-[10px] font-black italic animate-pulse">
36+
درحال بارگذاری...
37+
</div>
38+
) : (
39+
<div className="flex flex-row flex-wrap gap-1">
40+
{occupations.map((occupation) => {
41+
const isActive = selectedOccupation === occupation.id
42+
return (
43+
<button
44+
key={occupation.id}
45+
type="button"
46+
onClick={() => handleSelect(occupation.id)}
47+
className={`
48+
h-8 px-3 w-fit flex items-center justify-center
49+
text-[10px] font-black italic rounded-full text-muted border
50+
transition-all duration-200 active:scale-95 cursor-pointer
51+
${
52+
isActive
53+
? 'bg-primary border-primary shadow-sm text-white!'
54+
: 'bg-base-200/50 border-base-300/30 text-content hover:bg-base-200'
55+
}
56+
`}
57+
>
58+
{occupation.title}
59+
</button>
60+
)
61+
})}
62+
</div>
63+
)}
64+
</div>
65+
)
66+
67+
return (
68+
<>
69+
<button
70+
ref={triggerRef}
71+
type="button"
72+
onClick={() => setIsOpen(!isOpen)}
73+
className="flex items-center justify-between w-full p-3 text-right transition-colors hover:bg-content"
74+
>
75+
{triggerElement}
76+
</button>
77+
78+
<ClickableTooltip
79+
content={content}
80+
triggerRef={triggerRef}
81+
isOpen={isOpen}
82+
setIsOpen={setIsOpen}
83+
position="bottom"
84+
className=""
85+
/>
86+
</>
87+
)
88+
}

0 commit comments

Comments
 (0)