Skip to content

Commit 8b1e990

Browse files
authored
Merge branch 'main' into FixACARSSettings
2 parents 636c09d + 4fea0e7 commit 8b1e990

14 files changed

Lines changed: 1713 additions & 1028 deletions

File tree

public/assets/images/vatsim.svg

Lines changed: 0 additions & 11 deletions
This file was deleted.

public/assets/images/vatsim.webp

95.6 KB
Loading

src/components/AccessDenied.tsx

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ interface AccessDeniedProps {
1111
| 'access-denied'
1212
| 'invalid-session'
1313
| 'banned'
14-
| 'tester-required';
14+
| 'tester-required'
15+
| 'pilot-not-found';
1516
}
1617

1718
export default function AccessDenied({
@@ -28,18 +29,22 @@ export default function AccessDenied({
2829
errorType === 'invalid-session'
2930
? 'from-black via-zinc-900 to-yellow-700'
3031
: errorType === 'banned'
31-
? 'from-black via-zinc-900 to-red-900'
32-
: errorType === 'tester-required'
33-
? 'from-black via-zinc-900 to-cyan-900'
34-
: 'from-black via-zinc-900 to-red-950';
32+
? 'from-black via-zinc-900 to-red-900'
33+
: errorType === 'tester-required'
34+
? 'from-black via-zinc-900 to-cyan-900'
35+
: errorType === 'pilot-not-found'
36+
? 'from-black via-zinc-900 to-blue-900'
37+
: 'from-black via-zinc-900 to-red-950';
3538
const textGradient =
3639
errorType === 'invalid-session'
3740
? 'from-yellow-400 to-yellow-700'
3841
: errorType === 'banned'
39-
? 'from-red-400 to-red-700'
40-
: errorType === 'tester-required'
41-
? 'from-cyan-400 to-cyan-700'
42-
: 'from-red-400 to-red-900';
42+
? 'from-red-400 to-red-700'
43+
: errorType === 'tester-required'
44+
? 'from-cyan-400 to-cyan-700'
45+
: errorType === 'pilot-not-found'
46+
? 'from-blue-400 to-blue-700'
47+
: 'from-red-400 to-red-900';
4348

4449
if (errorType === 'invalid-session') {
4550
displayMessage = displayMessage || 'Invalid Session';
@@ -56,6 +61,11 @@ export default function AccessDenied({
5661
displayDescription =
5762
displayDescription ||
5863
'This application is currently in testing. Please contact an administrator if you believe you should have access.';
64+
} else if (errorType === 'pilot-not-found') {
65+
displayMessage = displayMessage || 'Pilot Not Found';
66+
displayDescription =
67+
displayDescription ||
68+
'The pilot you are looking for could not be found.';
5969
} else {
6070
displayMessage = displayMessage || 'Access Denied';
6171
displayDescription =
@@ -73,24 +83,27 @@ export default function AccessDenied({
7383
<h1
7484
className={`text-[10rem] font-extrabold bg-gradient-to-br ${textGradient} bg-clip-text text-transparent -mb-8`}
7585
>
76-
{errorType === 'invalid-session' ? '404' : '403'}
86+
{errorType === 'invalid-session' ||
87+
errorType === 'pilot-not-found'
88+
? '404'
89+
: '403'}
7790
</h1>
7891
<p className="text-2xl mb-4 text-gray-300">
7992
{displayMessage}
8093
</p>
8194
<p className="text-lg mb-8 text-gray-400">
8295
{displayDescription}
8396
</p>
84-
{errorType == 'tester-required' && (
97+
{errorType === 'tester-required' ||
98+
errorType === 'pilot-not-found' ? (
8599
<Link
86100
to="https://pfconnect.online/discord"
87101
className={`inline-flex items-center px-8 py-4 rounded-full ${'bg-[#4f62a5] hover:bg-[#384366]'} text-white text-xl font-medium transition-all duration-300 shadow-lg hover:shadow-xl`}
88102
>
89103
<FaDiscord className="mr-3 h-6 w-6 group-hover:-translate-x-1 transition-transform duration-300" />
90104
Support Server
91105
</Link>
92-
)}
93-
{errorType !== 'tester-required' && (
106+
) : (
94107
<Link
95108
to="https://pfconnect.online/discord"
96109
className={`inline-flex items-center px-8 py-4 rounded-full ${

src/components/Settings/AccountSettings.tsx

Lines changed: 43 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@ import Button from '../common/Button';
66
export default function AccountSettings() {
77
const { user, refreshUser } = useAuth();
88
const isVatsimLinked = !!(
9-
user?.vatsimCid || user?.vatsimRatingShort || user?.vatsimRatingLong
9+
user?.vatsimCid ||
10+
user?.vatsimRatingShort ||
11+
user?.vatsimRatingLong
1012
);
1113

1214
const handleLinkRoblox = () => {
@@ -16,17 +18,19 @@ export default function AccountSettings() {
1618
};
1719

1820
const handleLinkVatsim = () => {
19-
// Always force VATSIM to show the login/consent screen when linking
2021
window.location.href = `${import.meta.env.VITE_SERVER_URL}/api/auth/vatsim?force=1`;
2122
};
2223

2324
const handleUnlinkVatsim = async () => {
2425
if (!confirm('Unlink your VATSIM account?')) return;
2526
try {
26-
const res = await fetch(`${import.meta.env.VITE_SERVER_URL}/api/auth/vatsim/unlink`, {
27-
method: 'POST',
28-
credentials: 'include',
29-
});
27+
const res = await fetch(
28+
`${import.meta.env.VITE_SERVER_URL}/api/auth/vatsim/unlink`,
29+
{
30+
method: 'POST',
31+
credentials: 'include',
32+
}
33+
);
3034
if (res.ok) {
3135
await refreshUser();
3236
} else {
@@ -137,30 +141,55 @@ export default function AccountSettings() {
137141
{/* VATSIM Account */}
138142
<div className="bg-zinc-800/50 rounded-xl border-2 border-zinc-700/50 p-5 flex items-center justify-between">
139143
<div className="flex items-center space-x-4">
140-
<div className="w-12 h-12 bg-gradient-to-br from-green-500 to-emerald-600 rounded-xl flex items-center justify-center">
141-
<TowerControl className="w-7 h-7 text-white" />
144+
<div className="w-12 h-12 bg-white rounded-xl flex items-center justify-center">
145+
<img
146+
src="/assets/images/vatsim.webp"
147+
alt="VATSIM"
148+
className="w-8 h-8"
149+
/>
142150
</div>
143151
<div>
144-
<h3 className="text-white font-semibold text-base">VATSIM Account</h3>
152+
<h3 className="text-white font-semibold text-base">
153+
VATSIM Account
154+
</h3>
145155
{isVatsimLinked ? (
146156
<div className="flex items-center space-x-2 mt-1">
147-
<span className="text-green-400 text-sm font-medium">Connected</span>
157+
<span className="text-green-400 text-sm font-medium">
158+
Connected
159+
</span>
148160
<span className="text-zinc-500"></span>
149-
<span className="text-zinc-300 text-sm">{user?.vatsimRatingShort || user?.vatsimRatingLong || `CID ${user?.vatsimCid}`}</span>
161+
<span className="text-zinc-300 text-sm">
162+
{user?.vatsimRatingShort ||
163+
user?.vatsimRatingLong ||
164+
`CID ${user?.vatsimCid}`}
165+
</span>
150166
</div>
151167
) : (
152-
<p className="text-zinc-400 text-sm mt-1">Link your VATSIM account to show controller rating on your profile</p>
168+
<p className="text-zinc-400 text-sm mt-1">
169+
Link your VATSIM account to show controller
170+
rating on your profile
171+
</p>
153172
)}
154173
</div>
155174
</div>
156175
<div>
157176
{isVatsimLinked ? (
158-
<Button onClick={handleUnlinkVatsim} variant="outline" size="sm" className="border-red-700/50 text-red-400 hover:bg-red-900/20 hover:border-red-600">
177+
<Button
178+
onClick={handleUnlinkVatsim}
179+
variant="outline"
180+
size="sm"
181+
className="border-red-700/50 text-red-400 hover:bg-red-900/20 hover:border-red-600"
182+
>
159183
<UserX className="w-4 h-4 mr-2" />
160184
Unlink
161185
</Button>
162186
) : (
163-
<Button onClick={handleLinkVatsim} variant="primary" size="sm" className="bg-emerald-600 hover:bg-emerald-700 border-emerald-600">
187+
<Button
188+
onClick={handleLinkVatsim}
189+
variant="primary"
190+
size="sm"
191+
className="bg-emerald-600 hover:bg-emerald-700 border-emerald-600"
192+
>
164193
<ExternalLink className="w-4 h-4 mr-2" />
165194
Link Account
166195
</Button>

src/components/buttons/UserButton.tsx

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,20 @@ export default function CustomUserButton({
110110
</Link>
111111

112112
<div className="space-y-2">
113+
<button
114+
onClick={() =>
115+
handleAction(
116+
() =>
117+
(window.location.href =
118+
'/pilots/' + user.username)
119+
)
120+
}
121+
className="w-full flex items-center space-x-3 px-4 py-3 text-gray-300 hover:text-white hover:bg-zinc-800/60 rounded-xl transition-all duration-200 font-medium"
122+
>
123+
<User className="w-4 h-4" />
124+
<span>Profile</span>
125+
</button>
126+
113127
<button
114128
onClick={() =>
115129
handleAction(
@@ -204,11 +218,7 @@ export default function CustomUserButton({
204218

205219
{isDropdownOpen && (
206220
<div className="absolute right-0 mt-2 w-64 bg-zinc-900/95 backdrop-blur-md border border-zinc-800 rounded-xl shadow-2xl py-2 z-50 animate-in slide-in-from-top-1 duration-200">
207-
<Link
208-
to={`/pilots/${user.username}`}
209-
onClick={() => setIsDropdownOpen(false)}
210-
className="px-4 py-3 border-b border-gray-700/50 block hover:bg-zinc-800/50 transition-colors"
211-
>
221+
<div className="px-4 py-3 border-b border-gray-700/50 block cursor-default">
212222
<div className="flex items-center space-x-3">
213223
{user.avatar ? (
214224
<img
@@ -232,9 +242,21 @@ export default function CustomUserButton({
232242
)}
233243
</div>
234244
</div>
235-
</Link>
245+
</div>
236246

237247
<div className="py-1">
248+
<button
249+
onClick={() => {
250+
setIsDropdownOpen(false);
251+
window.location.href =
252+
'/pilots/' + user.username;
253+
}}
254+
className="w-full flex items-center space-x-3 px-4 py-3 text-gray-300 hover:bg-blue-600/20 hover:text-white transition-all duration-200 group"
255+
>
256+
<User className="w-4 h-4" />
257+
<span className="font-medium">Profile</span>
258+
</button>
259+
238260
<button
239261
onClick={() => {
240262
setIsDropdownOpen(false);

0 commit comments

Comments
 (0)