This commit is contained in:
2024-09-02 16:58:23 +02:00
parent c77503ed45
commit 1b0dc0f27d
52 changed files with 817 additions and 1379 deletions

View File

@@ -1,13 +1,101 @@
<script setup lang="ts">
definePageMeta({
middleware: 'auth',
})
const router = useRouter()
const date = ref<Date>(new Date())
onMounted(() => {
setInterval(() => date.value = new Date(), 1000)
})
const { user } = useUserSession()
onMounted(async () => {
if (user.value.username.toLowerCase() === router.currentRoute.value.params.user.toLowerCase()) {
await navigateTo('/')
}
})
const { data: userDetails } = await useAsyncData(async () => await $fetch(`/api/users/${router.currentRoute.value.params.user}`))
onMounted(() => {
if (userDetails.value.message) {
useErrorToast(userDetails.value.message, 'Look for another user.')
}
if (userDetails.value.private) {
useErrorToast('This user\'s profile is private.', 'Look for another user.')
}
})
</script>
<template>
<section>
{{ router.currentRoute.value.params.user }}
</section>
<main class="my-12">
<div v-if="date" class="flex flex-col items-center mb-12">
<h1 class="text-6xl md:text-9xl font-bold">
{{ useDateFormat(date, 'HH') }}
<span class="animate-pulse">:</span>
{{ useDateFormat(date, 'mm') }}
</h1>
<h1 class="text-2xl md:text-5xl">
{{ useDateFormat(date, 'dddd D MMMM YYYY', { locales: userDetails.locale ? userDetails.language : user.locale }) }}
</h1>
</div>
<div v-if="userDetails.message || userDetails.private" class="text-center mt-24 space-y-4">
<div
class="flex items-center justify-center gap-2 text-3xl"
:class="userDetails.message ? 'text-amber-500 dark:text-amber-400' : 'text-red-500 dark:text-red-400'"
>
<UIcon name="i-ph:warning-circle-duotone" />
<p>
{{ userDetails.message ? userDetails.message : 'This user\'s profile is private.' }}
</p>
</div>
<h1 class="text-lg italic text-neutral-600 dark:text-neutral-400">
Please look for another user.
</h1>
<UButton
label="Go to your page"
:color="userDetails.message ? 'amber' : 'red'"
size="xl"
icon="i-ph:house-line-duotone"
variant="outline"
to="/"
/>
</div>
<section v-else>
<div v-if="userDetails.categories.length > 0" class="space-y-12">
<div
v-for="category in userDetails.categories"
:key="category.id"
>
<div v-if="category" class="flex items-center mb-4" :class="category.nameVisible ? 'justify-between' : 'justify-end'">
<div v-if="category.nameVisible" class="flex items-center gap-2 mb-4" :class="`text-${category.color}-500`">
<UIcon :name="category.icon" size="28" />
<h1 class="font-bold text-2xl">
{{ category.name }}
</h1>
</div>
</div>
<div
v-if="userDetails.categories.filter(tab => tab.categoryId === category.id).length > 0"
class="grid grid-cols-1 auto-rows-auto sm:grid-cols-3 gap-4"
>
{{ userDetails.categories.filter(tab => tab.categoryId === category.id) }}
</div>
<div v-else class="flex gap-2 items-center">
<UIcon name="i-ph:empty-duotone" size="16" />
<h1 class="text-sm font-medium">
The category is empty.
</h1>
</div>
</div>
</div>
<div v-else class="flex gap-2 items-center">
<UIcon name="i-ph:empty-duotone" size="20" />
<h1 class="text-lg font-medium">
This user doesn't have any categories.
</h1>
</div>
</section>
</main>
</template>
<style scoped>
</style>

View File

@@ -1,4 +1,4 @@
<script lang="ts" setup>
<script setup lang="ts">
import type { CategoryType } from '~~/types/types'
definePageMeta({
@@ -10,10 +10,10 @@ onMounted(() => {
setInterval(() => date.value = new Date(), 1000)
})
const { user } = useUserSession()
const { user } = await useUserSession()
const { categories } = await useCategories()
const { getTabsForCategory } = await useTabs()
const { canCreateCategory } = await useUserLimit()
const { canCreateCategory } = await useUserLimits()
// Modals
const createCategoryModal = ref(false)
@@ -42,14 +42,23 @@ function openCreateTab(category: CategoryType) {
createTabModal.value = true
}
// Edit Tabs
const currentEditCategory = ref<CategoryType | null>(null)
// DropDown Items
const items = [[
{
label: 'Edit',
label: 'Edit Category',
icon: 'i-ph:pencil-duotone',
color: 'green',
click: category => openUpdateCategoryModal(category),
},
{
label: 'Edit Tabs',
icon: 'i-ph:cards-three-duotone',
color: 'amber',
click: category => currentEditCategory.value?.id === category.id ? currentEditCategory.value = null : currentEditCategory.value = category,
},
{
label: 'Delete',
icon: 'i-ph:trash-duotone',
@@ -64,6 +73,23 @@ defineShortcuts({
createCategoryModal.value = true
}
},
escape: () => {
if (createCategoryModal.value) {
createCategoryModal.value = false
}
if (updateCategoryModal.value) {
updateCategoryModal.value = false
}
if (deleteCategoryModal.value) {
deleteCategoryModal.value = false
}
if (createTabModal.value) {
createTabModal.value = false
}
if (currentEditCategory.value) {
currentEditCategory.value = null
}
},
})
</script>
@@ -116,11 +142,15 @@ defineShortcuts({
:category="category"
@create-tab="openCreateTab(category)"
/>
<div v-if="getTabsForCategory(category.id).length > 0" class="grid grid-cols-1 auto-rows-auto sm:grid-cols-3 md:grid-cols-4 gap-4">
<div
v-if="getTabsForCategory(category.id).length > 0"
class="grid grid-cols-1 auto-rows-auto sm:grid-cols-3 gap-4"
>
<AppTab
v-for="tab in getTabsForCategory(category.id)"
:key="tab.id"
:tab="tab"
:edit-mode="currentEditCategory?.id === category.id"
/>
</div>
<div v-else class="flex gap-2 items-center">

View File

@@ -1,29 +1,13 @@
<script lang="ts" setup>
import { z } from 'zod'
import { useSession } from 'h3'
import type { FormSubmitEvent } from '#ui/types'
const { loggedIn } = useUserSession()
const { loggedIn } = await useUserSession()
definePageMeta({
middleware: 'ghost',
layout: 'login',
})
const schema = z.object({
email: z.string().email('Invalid email'),
})
type Schema = z.output<typeof schema>
const state = reactive({ email: undefined })
async function onSubmit(event: FormSubmitEvent<Schema>) {
// Do something with data
// todo: add login logic
console.log(event.data)
state.email = ''
}
const message = useState<string>('message')
if (import.meta.server) {
const session = await useSession(useRequestEvent()!, {
@@ -62,20 +46,6 @@ if (import.meta.server) {
</template>
<template #default>
<div v-if="!loggedIn" class="flex flex-col gap-4 p-4">
<UForm :schema="schema" :state="state" class="space-y-4" @submit="onSubmit">
<UFormGroup name="email">
<UInput v-model="state.email" color="gray" placeholder="arthur@arthome.com" />
</UFormGroup>
<UButton
:external="true"
color="gray"
icon="i-ph:envelope-duotone"
label="Continue with Email"
block
type="submit"
/>
</UForm>
<UDivider label="or" />
<UButton
:external="true"
color="gray"