You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

197 lines
4.5 KiB
TypeScript

import { db } from '$lib/db'
import {
and,
asc,
desc,
eq,
getTableColumns,
ilike,
sql,
} from 'drizzle-orm'
import type { PageServerLoad } from './$types'
import { project, shortener, visitor } from '$lib/db/schema'
import { fail, setError, superValidate } from 'sveltekit-superforms'
import { zod } from 'sveltekit-superforms/adapters'
import { formSchema } from './schema'
import type { Actions } from './$types'
import { nanoid } from 'nanoid'
export const load = (async (event) => {
const user = event.locals.user
const project_uuid = event.url.searchParams.get('project')
const search = event.url.searchParams.get('search')
let sortBy = event.url.searchParams.get('sortBy')
let page = parseInt(event.url.searchParams.get('page') ?? '1')
let perPage = parseInt(
event.url.searchParams.get('perPage') ?? '12',
)
if (isNaN(page)) {
page = 1
}
if (isNaN(perPage)) {
perPage = 10
}
if (
sortBy !== 'latest' &&
sortBy !== 'oldest' &&
sortBy !== 'most_visited'
) {
sortBy = 'latest'
}
let project_id: number | undefined
let selected_project: { value: null | string; label: string } = {
value: null,
label: 'All',
}
if (project_uuid) {
try {
const project = await db.query.project.findFirst({
where: (project, { eq }) => eq(project.uuid, project_uuid),
})
project_id = project?.id
if (project?.name) {
selected_project.label = project.name
selected_project.value = project.uuid
}
} catch (error) {
project_id = undefined
}
}
const shortenerColumns = getTableColumns(shortener)
const projectColumns = getTableColumns(project)
const shorteners = db
.select({
...shortenerColumns,
projectName: project.name,
projectUuid: project.uuid,
project: { ...projectColumns },
visitorCount: sql<number>`count(${visitor.id})`,
})
.from(shortener)
.where(
and(
eq(shortener.userId, user.id),
project_id ? eq(shortener.projectId, project_id) : undefined,
search
? ilike(shortener.link, `%${decodeURI(search)}%`)
: undefined,
),
)
.leftJoin(visitor, eq(shortener.id, visitor.shortenerId))
.leftJoin(project, eq(shortener.projectId, project.id))
.groupBy(shortener.id, project.id)
.offset(perPage * (page - 1))
.limit(perPage)
const pagination = db
.select({
total: sql<number>`count(*)`.as('total'),
})
.from(shortener)
.where(
and(
eq(shortener.userId, user.id),
project_id ? eq(shortener.projectId, project_id) : undefined,
search
? ilike(shortener.link, `%${decodeURI(search)}%`)
: undefined,
),
)
if (sortBy === 'latest') {
shorteners.orderBy(desc(shortener.createdAt))
} else if (sortBy === 'oldest') {
shorteners.orderBy(asc(shortener.createdAt))
} else if (sortBy === 'most_visited') {
shorteners.orderBy(sql`count(${visitor.id}) desc`)
}
const projects = db.query.project.findMany({
where: (project, { eq }) => eq(project.userId, user.id),
})
const settings = db.query.setting.findFirst({
where: (settings, { eq }) => eq(settings.userId, user.id),
})
return {
shorteners,
projects: await projects,
selected_project,
settings: await settings,
page,
perPage,
search,
sortBy,
pagination,
form: await superValidate({ active: true }, zod(formSchema), {
errors: false,
}),
}
}) satisfies PageServerLoad
export const actions: Actions = {
create: async (event) => {
const form = await superValidate(event, zod(formSchema))
if (!form.valid) {
return fail(400, {
form,
})
}
if (form.data.custom_code_enable) {
if (!form.data.custom_code) {
return setError(
form,
'custom_code',
'Please Enter Custom Code',
)
}
const customCodeExist = await db.query.shortener.findFirst({
where: (shortener, { eq }) =>
eq(shortener.code, form.data.custom_code),
})
if (customCodeExist) {
return setError(form, 'custom_code', 'Duplicated Custom Code')
}
}
const user = event.locals.user
let project = undefined
const selected_project = form.data.project
if (selected_project) {
project = await db.query.project.findFirst({
where: (project, { eq, and }) =>
and(
eq(project.userId, user.id),
eq(project.uuid, selected_project),
),
})
}
const code = form.data.custom_code_enable
? form.data.custom_code
: nanoid(8)
await db.insert(shortener).values({
link: form.data.link,
projectId: project?.id,
userId: user.id,
code: code,
ios: form.data.ios,
ios_link: form.data.ios_link,
android: form.data.android,
android_link: form.data.android_link,
})
return { form }
},
}