chore:linting,formatting,type fixing, ....

This commit is contained in:
2025-11-08 14:39:33 +01:00
parent 0754d62d0e
commit ae339d68e1
17 changed files with 86 additions and 74 deletions

View File

@@ -25,7 +25,17 @@ export default defineConfig(
rules: {
// typescript-eslint strongly recommend that you do not use the no-undef lint rule on TypeScript projects.
// see: https://typescript-eslint.io/troubleshooting/faqs/eslint/#i-get-errors-from-the-no-undef-rule-about-global-variables-not-being-defined-even-though-there-are-no-typescript-errors
'no-undef': 'off'
'no-undef': 'off',
// Disable no-navigation-without-resolve as we're using resolveRoute from $app/paths
'svelte/no-navigation-without-resolve': 'off',
// Allow unused vars that start with underscore
'@typescript-eslint/no-unused-vars': [
'error',
{
argsIgnorePattern: '^_',
varsIgnorePattern: '^_'
}
]
}
},
{

View File

@@ -56,7 +56,7 @@
await apiSync.deleteComment(commentId, findId);
}
function canDeleteComment(comment: any): boolean {
function canDeleteComment(comment: { user: { id: string } }): boolean {
return Boolean(
currentUserId && (comment.user.id === currentUserId || comment.user.id === 'current-user')
);
@@ -65,7 +65,7 @@
{#snippet loadingSkeleton()}
<div class="loading-skeleton">
{#each Array(3) as _}
{#each Array(3) as _, index (index)}
<div class="comment-skeleton">
<Skeleton class="avatar-skeleton" />
<div class="content-skeleton">

View File

@@ -1,5 +1,6 @@
<script lang="ts">
import { ProfilePanel } from '$lib';
import { resolveRoute } from '$app/paths';
type User = {
id: string;
@@ -12,7 +13,7 @@
<header class="app-header">
<div class="header-content">
<h1 class="app-title"><a href="/">Serengo</a></h1>
<h1 class="app-title"><a href={resolveRoute('/')}>Serengo</a></h1>
<div class="profile-container">
<ProfilePanel
username={user.username}

View File

@@ -28,7 +28,7 @@
isLoading: false
});
let apiSync: any = null;
let apiSync: typeof import('$lib/stores/api-sync').apiSync | null = null;
// Initialize API sync and subscribe to global state
onMount(async () => {
@@ -65,13 +65,15 @@
// Subscribe to global state for this find
const globalLikeState = apiSync.subscribeFindLikes(findId);
globalLikeState.subscribe((state: any) => {
globalLikeState.subscribe(
(state: { isLiked: boolean; likeCount: number; isLoading: boolean }) => {
likeState.set({
isLiked: state.isLiked,
likeCount: state.likeCount,
isLoading: state.isLoading
});
});
}
);
} catch (error) {
console.error('Failed to initialize API sync:', error);
}
@@ -81,8 +83,7 @@
async function toggleLike() {
if (!apiSync || !browser) return;
const currentState = likeState;
if (currentState && (currentState as any).isLoading) return;
if ($likeState.isLoading) return;
try {
await apiSync.toggleLike(findId);

View File

@@ -9,8 +9,6 @@
*/
let permissionStatus = $state<NotificationPermission>('default');
let subscriptionStatus = $state<'idle' | 'subscribing' | 'subscribed' | 'error'>('idle');
let errorMessage = $state<string>('');
let showPrompt = $state<boolean>(false);
let isSupported = $state<boolean>(false);
@@ -57,8 +55,6 @@
}
} catch (error) {
console.error('[NotificationManager] Error initializing notifications:', error);
subscriptionStatus = 'error';
errorMessage = error instanceof Error ? error.message : 'Unknown error';
}
}
@@ -75,13 +71,9 @@
await subscribeToNotifications();
} else {
console.log('[NotificationManager] Permission not granted');
subscriptionStatus = 'error';
errorMessage = 'Notification permission was not granted';
}
} catch (error) {
console.error('[NotificationManager] Error enabling notifications:', error);
subscriptionStatus = 'error';
errorMessage = error instanceof Error ? error.message : 'Unknown error';
}
}
@@ -94,7 +86,6 @@
async function subscribeToNotifications() {
try {
console.log('[NotificationManager] subscribeToNotifications called');
subscriptionStatus = 'subscribing';
// Get or register service worker
let registration = await navigator.serviceWorker.getRegistration();
@@ -161,12 +152,9 @@
throw new Error('Failed to save subscription to server');
}
subscriptionStatus = 'subscribed';
console.log('[NotificationManager] Successfully subscribed to push notifications!');
} catch (error) {
console.error('[NotificationManager] Error subscribing to push notifications:', error);
subscriptionStatus = 'error';
errorMessage = error instanceof Error ? error.message : 'Unknown error';
}
}

View File

@@ -36,17 +36,16 @@
isLoading = true;
try {
const params = new URLSearchParams({
action: 'autocomplete',
query: query.trim()
});
const searchParams = new URL('/api/places', window.location.origin).searchParams;
searchParams.set('action', 'autocomplete');
searchParams.set('query', query.trim());
if ($coordinates) {
params.set('lat', $coordinates.latitude.toString());
params.set('lng', $coordinates.longitude.toString());
searchParams.set('lat', $coordinates.latitude.toString());
searchParams.set('lng', $coordinates.longitude.toString());
}
const response = await fetch(`/api/places?${params}`);
const response = await fetch(`/api/places?${searchParams}`);
if (response.ok) {
suggestions = await response.json();
showSuggestions = true;
@@ -179,7 +178,7 @@
<div class="suggestion-content">
<span class="suggestion-name">{suggestion.description}</span>
<div class="suggestion-types">
{#each suggestion.types.slice(0, 2) as type}
{#each suggestion.types.slice(0, 2) as type, index (index)}
<span class="suggestion-type">{type.replace(/_/g, ' ')}</span>
{/each}
</div>

View File

@@ -1,5 +1,6 @@
<script lang="ts">
import { enhance } from '$app/forms';
import { resolveRoute } from '$app/paths';
import {
DropdownMenu,
DropdownMenuContent,
@@ -81,7 +82,7 @@
</DropdownMenuItem>
<DropdownMenuItem class="friends-item">
<a href="/friends" class="friends-link">Friends</a>
<a href={resolveRoute('/friends')} class="friends-link">Friends</a>
</DropdownMenuItem>
<DropdownMenuItem class="notification-settings-item" onclick={openNotificationSettingsSheet}>

View File

@@ -2,6 +2,7 @@
import { cn, type WithElementRef } from '$lib/utils.js';
import type { HTMLAnchorAttributes, HTMLButtonAttributes } from 'svelte/elements';
import { type VariantProps, tv } from 'tailwind-variants';
import { resolveRoute } from '$app/paths';
export const buttonVariants = tv({
base: "focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive inline-flex shrink-0 items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium outline-none transition-all focus-visible:ring-[3px] disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 [&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none [&_svg]:shrink-0",
@@ -58,7 +59,7 @@
bind:this={ref}
data-slot="button"
class={cn(buttonVariants({ variant, size }), className)}
href={disabled ? undefined : href}
href={disabled ? undefined : resolveRoute(href)}
aria-disabled={disabled}
role={disabled ? 'link' : undefined}
tabindex={disabled ? -1 : undefined}

View File

@@ -1,6 +1,7 @@
<script lang="ts">
import { enhance } from '$app/forms';
import { goto } from '$app/navigation';
import { resolveRoute } from '$app/paths';
import { Button } from '$lib/components/button/index.js';
import * as Card from '$lib/components/card/index.js';
import { Label } from '$lib/components/label/index.js';
@@ -62,7 +63,11 @@
</Button>
</div>
</div>
<Button variant="outline" class="mt-4 w-full" onclick={() => goto('/login/google')}>
<Button
variant="outline"
class="mt-4 w-full"
onclick={() => goto(resolveRoute('/login/google'))}
>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<path
d="M12.48 10.92v3.28h7.84c-.24 1.84-.853 3.187-1.787 4.133-1.147 1.147-2.933 2.4-6.053 2.4-4.827 0-8.6-3.893-8.6-8.72s3.773-8.72 8.6-8.72c2.6 0 4.507 1.027 5.907 2.347l2.307-2.307C18.747 1.44 16.133 0 12.48 0 5.867 0 .307 5.387.307 12s5.56 12 12.173 12c3.573 0 6.267-1.173 8.373-3.36 2.16-2.16 2.84-5.213 2.84-7.667 0-.76-.053-1.467-.173-2.053H12.48z"

View File

@@ -4,7 +4,11 @@ import type { NotificationInsert } from './db/schema';
import { eq, and, desc } from 'drizzle-orm';
import { nanoid } from 'nanoid';
export type NotificationType = 'friend_request' | 'friend_accepted' | 'find_liked' | 'find_commented';
export type NotificationType =
| 'friend_request'
| 'friend_accepted'
| 'find_liked'
| 'find_commented';
export interface CreateNotificationData {
userId: string;
@@ -106,10 +110,7 @@ export class NotificationService {
*/
async markAsRead(notificationIds: string[]): Promise<void> {
for (const id of notificationIds) {
await db
.update(notification)
.set({ isRead: true })
.where(eq(notification.id, id));
await db.update(notification).set({ isRead: true }).where(eq(notification.id, id));
}
}
@@ -117,20 +118,14 @@ export class NotificationService {
* Mark a single notification as read
*/
async markOneAsRead(notificationId: string): Promise<void> {
await db
.update(notification)
.set({ isRead: true })
.where(eq(notification.id, notificationId));
await db.update(notification).set({ isRead: true }).where(eq(notification.id, notificationId));
}
/**
* Mark all notifications as read for a user
*/
async markAllAsRead(userId: string): Promise<void> {
await db
.update(notification)
.set({ isRead: true })
.where(eq(notification.userId, userId));
await db.update(notification).set({ isRead: true }).where(eq(notification.userId, userId));
}
/**

View File

@@ -4,11 +4,7 @@ import { notificationSubscription } from './db/schema';
import type { NotificationSubscriptionInsert } from './db/schema';
import { eq, and } from 'drizzle-orm';
import { nanoid } from 'nanoid';
import {
VAPID_PUBLIC_KEY,
VAPID_PRIVATE_KEY,
VAPID_SUBJECT
} from '$env/static/private';
import { VAPID_PUBLIC_KEY, VAPID_PRIVATE_KEY, VAPID_SUBJECT } from '$env/static/private';
// Initialize web-push with VAPID keys
if (!VAPID_PUBLIC_KEY || !VAPID_PRIVATE_KEY || !VAPID_SUBJECT) {
@@ -88,7 +84,10 @@ export class PushService {
await db
.delete(notificationSubscription)
.where(
and(eq(notificationSubscription.userId, userId), eq(notificationSubscription.endpoint, endpoint))
and(
eq(notificationSubscription.userId, userId),
eq(notificationSubscription.endpoint, endpoint)
)
);
}
@@ -100,7 +99,10 @@ export class PushService {
.select()
.from(notificationSubscription)
.where(
and(eq(notificationSubscription.userId, userId), eq(notificationSubscription.isActive, true))
and(
eq(notificationSubscription.userId, userId),
eq(notificationSubscription.isActive, true)
)
);
}

View File

@@ -76,7 +76,7 @@ export const POST: RequestHandler = async ({ params, locals, request }) => {
const commentId = crypto.randomUUID();
const now = new Date();
const [newComment] = await db
await db
.insert(findComment)
.values({
id: commentId,
@@ -115,7 +115,10 @@ export const POST: RequestHandler = async ({ params, locals, request }) => {
if (findData.length > 0 && findData[0].userId !== session.userId) {
const findOwner = findData[0];
const shouldNotify = await notificationService.shouldNotify(findOwner.userId, 'find_commented');
const shouldNotify = await notificationService.shouldNotify(
findOwner.userId,
'find_commented'
);
if (shouldNotify) {
// Get commenter's username

View File

@@ -1,7 +1,7 @@
import { json } from '@sveltejs/kit';
import { db } from '$lib/server/db';
import { findComment, user } from '$lib/server/db/schema';
import { eq, and } from 'drizzle-orm';
import { findComment } from '$lib/server/db/schema';
import { eq } from 'drizzle-orm';
import type { RequestHandler } from './$types';
export const DELETE: RequestHandler = async ({ params, locals }) => {

View File

@@ -41,7 +41,10 @@ export const PATCH: RequestHandler = async ({ locals, request }) => {
} else if (Array.isArray(notificationIds) && notificationIds.length > 0) {
await notificationService.markAsRead(notificationIds);
} else {
return json({ error: 'Invalid request: provide notificationIds or markAll' }, { status: 400 });
return json(
{ error: 'Invalid request: provide notificationIds or markAll' },
{ status: 400 }
);
}
return json({ success: true });
@@ -66,7 +69,10 @@ export const DELETE: RequestHandler = async ({ locals, request }) => {
} else if (notificationId) {
await notificationService.deleteNotification(notificationId, user.id);
} else {
return json({ error: 'Invalid request: provide notificationId or deleteAll' }, { status: 400 });
return json(
{ error: 'Invalid request: provide notificationId or deleteAll' },
{ status: 400 }
);
}
return json({ success: true });

View File

@@ -134,10 +134,10 @@
// Search users when query changes with debounce
let searchTimeout: ReturnType<typeof setTimeout>;
$effect(() => {
// Track searchQuery dependency explicitly
searchQuery;
if (searchQuery) {
clearTimeout(searchTimeout);
searchTimeout = setTimeout(searchUsers, 300);
}
});
</script>