Skip to content

Commit 8e533b1

Browse files
Add desktop app directory with Remix application code
1 parent 833259c commit 8e533b1

383 files changed

Lines changed: 70034 additions & 0 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
import * as DropdownMenu from '@radix-ui/react-dropdown-menu';
2+
import { motion } from 'framer-motion';
3+
import { useStore } from '@nanostores/react';
4+
import { classNames } from '~/utils/classNames';
5+
import { profileStore } from '~/lib/stores/profile';
6+
import type { TabType, Profile } from './types';
7+
8+
interface AvatarDropdownProps {
9+
onSelectTab: (tab: TabType) => void;
10+
}
11+
12+
export const AvatarDropdown = ({ onSelectTab }: AvatarDropdownProps) => {
13+
const profile = useStore(profileStore) as Profile;
14+
15+
return (
16+
<DropdownMenu.Root>
17+
<DropdownMenu.Trigger asChild>
18+
<motion.button
19+
className="w-10 h-10 rounded-full bg-transparent flex items-center justify-center focus:outline-none"
20+
whileHover={{ scale: 1.02 }}
21+
whileTap={{ scale: 0.98 }}
22+
>
23+
{profile?.avatar ? (
24+
<img
25+
src={profile.avatar}
26+
alt={profile?.username || 'Profile'}
27+
className="w-full h-full rounded-full object-cover"
28+
loading="eager"
29+
decoding="sync"
30+
/>
31+
) : (
32+
<div className="w-full h-full rounded-full flex items-center justify-center bg-white dark:bg-gray-800 text-gray-400 dark:text-gray-500">
33+
<div className="i-ph:user w-6 h-6" />
34+
</div>
35+
)}
36+
</motion.button>
37+
</DropdownMenu.Trigger>
38+
39+
<DropdownMenu.Portal>
40+
<DropdownMenu.Content
41+
className={classNames(
42+
'min-w-[240px] z-[250]',
43+
'bg-white dark:bg-[#141414]',
44+
'rounded-lg shadow-lg',
45+
'border border-gray-200/50 dark:border-gray-800/50',
46+
'animate-in fade-in-0 zoom-in-95',
47+
'py-1',
48+
)}
49+
sideOffset={5}
50+
align="end"
51+
>
52+
<div
53+
className={classNames(
54+
'px-4 py-3 flex items-center gap-3',
55+
'border-b border-gray-200/50 dark:border-gray-800/50',
56+
)}
57+
>
58+
<div className="w-10 h-10 rounded-full overflow-hidden flex-shrink-0 bg-white dark:bg-gray-800 shadow-sm">
59+
{profile?.avatar ? (
60+
<img
61+
src={profile.avatar}
62+
alt={profile?.username || 'Profile'}
63+
className={classNames('w-full h-full', 'object-cover', 'transform-gpu', 'image-rendering-crisp')}
64+
loading="eager"
65+
decoding="sync"
66+
/>
67+
) : (
68+
<div className="w-full h-full flex items-center justify-center text-gray-400 dark:text-gray-500 font-medium text-lg">
69+
<div className="i-ph:user w-6 h-6" />
70+
</div>
71+
)}
72+
</div>
73+
<div className="flex-1 min-w-0">
74+
<div className="font-medium text-sm text-gray-900 dark:text-white truncate">
75+
{profile?.username || 'Guest User'}
76+
</div>
77+
{profile?.bio && <div className="text-xs text-gray-500 dark:text-gray-400 truncate">{profile.bio}</div>}
78+
</div>
79+
</div>
80+
81+
<DropdownMenu.Item
82+
className={classNames(
83+
'flex items-center gap-2 px-4 py-2.5',
84+
'text-sm text-gray-700 dark:text-gray-200',
85+
'hover:bg-purple-50 dark:hover:bg-purple-500/10',
86+
'hover:text-purple-500 dark:hover:text-purple-400',
87+
'cursor-pointer transition-all duration-200',
88+
'outline-none',
89+
'group',
90+
)}
91+
onClick={() => onSelectTab('profile')}
92+
>
93+
<div className="i-ph:user-circle w-4 h-4 text-gray-400 group-hover:text-purple-500 dark:group-hover:text-purple-400 transition-colors" />
94+
Edit Profile
95+
</DropdownMenu.Item>
96+
97+
<DropdownMenu.Item
98+
className={classNames(
99+
'flex items-center gap-2 px-4 py-2.5',
100+
'text-sm text-gray-700 dark:text-gray-200',
101+
'hover:bg-purple-50 dark:hover:bg-purple-500/10',
102+
'hover:text-purple-500 dark:hover:text-purple-400',
103+
'cursor-pointer transition-all duration-200',
104+
'outline-none',
105+
'group',
106+
)}
107+
onClick={() => onSelectTab('settings')}
108+
>
109+
<div className="i-ph:gear-six w-4 h-4 text-gray-400 group-hover:text-purple-500 dark:group-hover:text-purple-400 transition-colors" />
110+
Settings
111+
</DropdownMenu.Item>
112+
113+
<div className="my-1 border-t border-gray-200/50 dark:border-gray-800/50" />
114+
115+
<DropdownMenu.Item
116+
className={classNames(
117+
'flex items-center gap-2 px-4 py-2.5',
118+
'text-sm text-gray-700 dark:text-gray-200',
119+
'hover:bg-purple-50 dark:hover:bg-purple-500/10',
120+
'hover:text-purple-500 dark:hover:text-purple-400',
121+
'cursor-pointer transition-all duration-200',
122+
'outline-none',
123+
'group',
124+
)}
125+
onClick={() =>
126+
window.open('https://github.com/Gerome-Elassaad/codingit/issues/new?template=bug_report.yml', '_blank')
127+
}
128+
>
129+
<div className="i-ph:bug w-4 h-4 text-gray-400 group-hover:text-purple-500 dark:group-hover:text-purple-400 transition-colors" />
130+
Report Bug
131+
</DropdownMenu.Item>
132+
133+
<DropdownMenu.Item
134+
className={classNames(
135+
'flex items-center gap-2 px-4 py-2.5',
136+
'text-sm text-gray-700 dark:text-gray-200',
137+
'hover:bg-purple-50 dark:hover:bg-purple-500/10',
138+
'hover:text-purple-500 dark:hover:text-purple-400',
139+
'cursor-pointer transition-all duration-200',
140+
'outline-none',
141+
'group',
142+
)}
143+
onClick={async () => {
144+
try {
145+
const { downloadDebugLog } = await import('~/utils/debugLogger');
146+
await downloadDebugLog();
147+
} catch (error) {
148+
console.error('Failed to download debug log:', error);
149+
}
150+
}}
151+
>
152+
<div className="i-ph:download w-4 h-4 text-gray-400 group-hover:text-purple-500 dark:group-hover:text-purple-400 transition-colors" />
153+
Download Debug Log
154+
</DropdownMenu.Item>
155+
156+
<DropdownMenu.Item
157+
className={classNames(
158+
'flex items-center gap-2 px-4 py-2.5',
159+
'text-sm text-gray-700 dark:text-gray-200',
160+
'hover:bg-purple-50 dark:hover:bg-purple-500/10',
161+
'hover:text-purple-500 dark:hover:text-purple-400',
162+
'cursor-pointer transition-all duration-200',
163+
'outline-none',
164+
'group',
165+
)}
166+
onClick={() => window.open('https://gerome-elassaad.github.io/codinit-app/', '_blank')}
167+
>
168+
<div className="i-ph:question w-4 h-4 text-gray-400 group-hover:text-purple-500 dark:group-hover:text-purple-400 transition-colors" />
169+
Help & Documentation
170+
</DropdownMenu.Item>
171+
</DropdownMenu.Content>
172+
</DropdownMenu.Portal>
173+
</DropdownMenu.Root>
174+
);
175+
};

0 commit comments

Comments
 (0)