rename proyecto a Alpha, refactor imports a components/ui, fix types en stores
This commit is contained in:
@@ -49,7 +49,7 @@ function setTab(tab: string) {
|
||||
</div>
|
||||
<div class="grid flex-1 text-left text-sm leading-tight">
|
||||
<span class="truncate font-semibold">Alpha</span>
|
||||
<span class="truncate text-xs">KAPPA Hub</span>
|
||||
<span class="truncate text-xs">Alpha</span>
|
||||
</div>
|
||||
</SidebarMenuButton>
|
||||
</SidebarMenuItem>
|
||||
|
||||
@@ -22,28 +22,16 @@ import {
|
||||
SidebarContent,
|
||||
SidebarFooter,
|
||||
SidebarHeader,
|
||||
SidebarMenu,
|
||||
SidebarMenuButton,
|
||||
SidebarMenuItem,
|
||||
} from "@/components/ui/sidebar"
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Sidebar collapsible="offcanvas">
|
||||
<SidebarHeader>
|
||||
<SidebarMenu>
|
||||
<SidebarMenuItem>
|
||||
<SidebarMenuButton
|
||||
as-child
|
||||
class="data-[slot=sidebar-menu-button]:!p-1.5"
|
||||
>
|
||||
<a href="#">
|
||||
<IconInnerShadowTop class="!size-5" />
|
||||
<span class="text-base font-semibold">KAPPA Hub</span>
|
||||
</a>
|
||||
</SidebarMenuButton>
|
||||
</SidebarMenuItem>
|
||||
</SidebarMenu>
|
||||
<div class="flex items-center gap-2 px-3 py-2">
|
||||
<IconInnerShadowTop class="size-5" />
|
||||
<span class="text-base font-semibold">Alpha</span>
|
||||
</div>
|
||||
</SidebarHeader>
|
||||
<SidebarContent>
|
||||
<NavMain />
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
import type { ChartConfig } from "@/registry/new-york-v4/ui/chart"
|
||||
import { ref, computed } from "vue"
|
||||
import type { ChartConfig } from "@/components/ui/chart"
|
||||
|
||||
// import { Area, AreaChart, CartesianGrid, XAxis, YAxis } from "recharts"
|
||||
import { VisArea, VisAxis, VisLine, VisXYContainer } from "@unovis/vue"
|
||||
@@ -9,7 +10,7 @@ import {
|
||||
CardDescription,
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} from "@/registry/new-york-v4/ui/card"
|
||||
} from "@/components/ui/card"
|
||||
import {
|
||||
|
||||
ChartContainer,
|
||||
@@ -18,14 +19,14 @@ import {
|
||||
ChartTooltip,
|
||||
ChartTooltipContent,
|
||||
componentToString,
|
||||
} from "@/registry/new-york-v4/ui/chart"
|
||||
} from "@/components/ui/chart"
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from "@/registry/new-york-v4/ui/select"
|
||||
} from "@/components/ui/select"
|
||||
|
||||
const description = "An interactive area chart"
|
||||
|
||||
@@ -257,7 +258,7 @@ const filterRange = computed(() => {
|
||||
<ChartTooltip />
|
||||
<ChartCrosshair
|
||||
:template="componentToString(chartConfig, ChartTooltipContent, {
|
||||
labelFormatter: (d) => {
|
||||
labelFormatter: (d: number) => {
|
||||
return new Date(d).toLocaleDateString('en-US', {
|
||||
month: 'short',
|
||||
day: 'numeric',
|
||||
|
||||
@@ -15,6 +15,7 @@ export const schema = z.object({
|
||||
</script>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { h, ref, computed } from "vue"
|
||||
import type {
|
||||
ColumnDef,
|
||||
ColumnFiltersState,
|
||||
@@ -43,10 +44,10 @@ import {
|
||||
useVueTable,
|
||||
} from "@tanstack/vue-table"
|
||||
import { DragDropProvider } from "dnd-kit-vue"
|
||||
import { Badge } from "@/registry/new-york-v4/ui/badge"
|
||||
import { Badge } from "@/components/ui/badge"
|
||||
|
||||
import { Button } from "@/registry/new-york-v4/ui/button"
|
||||
import { Checkbox } from "@/registry/new-york-v4/ui/checkbox"
|
||||
import { Button } from "@/components/ui/button"
|
||||
import { Checkbox } from "@/components/ui/checkbox"
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuCheckboxItem,
|
||||
@@ -54,16 +55,16 @@ import {
|
||||
DropdownMenuItem,
|
||||
DropdownMenuSeparator,
|
||||
DropdownMenuTrigger,
|
||||
} from "@/registry/new-york-v4/ui/dropdown-menu"
|
||||
} from "@/components/ui/dropdown-menu"
|
||||
|
||||
import { Label } from "@/registry/new-york-v4/ui/label"
|
||||
import { Label } from "@/components/ui/label"
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from "@/registry/new-york-v4/ui/select"
|
||||
} from "@/components/ui/select"
|
||||
import {
|
||||
Table,
|
||||
TableBody,
|
||||
@@ -71,14 +72,14 @@ import {
|
||||
TableHead,
|
||||
TableHeader,
|
||||
TableRow,
|
||||
} from "@/registry/new-york-v4/ui/table"
|
||||
} from "@/components/ui/table"
|
||||
|
||||
import {
|
||||
Tabs,
|
||||
TabsContent,
|
||||
TabsList,
|
||||
TabsTrigger,
|
||||
} from "@/registry/new-york-v4/ui/tabs"
|
||||
} from "@/components/ui/tabs"
|
||||
|
||||
const props = defineProps<{
|
||||
data: TableData[]
|
||||
@@ -108,7 +109,7 @@ const columns: ColumnDef<TableData>[] = [
|
||||
{
|
||||
id: "select",
|
||||
header: ({ table }) => h(Checkbox, {
|
||||
"modelValue": table.getIsAllPageRowsSelected() || (table.getIsSomePageRowsSelected() && "indeterminate"),
|
||||
"modelValue": table.getIsAllPageRowsSelected(),
|
||||
"onUpdate:modelValue": value => table.toggleAllPageRowsSelected(!!value),
|
||||
"aria-label": "Select all",
|
||||
}),
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
import { IconGripVertical } from "@tabler/icons-vue"
|
||||
import { useSortableContext } from "dnd-kit-vue"
|
||||
import { Button } from "@/registry/new-york-v4/ui/button"
|
||||
import { Button } from "@/components/ui/button"
|
||||
|
||||
const { handleRef, sortable } = useSortableContext()
|
||||
</script>
|
||||
|
||||
@@ -7,7 +7,7 @@ import { useSortable } from "dnd-kit-vue"
|
||||
import {
|
||||
TableCell,
|
||||
TableRow,
|
||||
} from "@/registry/new-york-v4/ui/table"
|
||||
} from "@/components/ui/table"
|
||||
|
||||
const props = defineProps<{ row: Row<z.infer<typeof schema>>, index: number }>()
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ import {
|
||||
Avatar,
|
||||
AvatarFallback,
|
||||
AvatarImage,
|
||||
} from "@/registry/new-york-v4/ui/avatar"
|
||||
} from "@/components/ui/avatar"
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
@@ -20,13 +20,13 @@ import {
|
||||
DropdownMenuLabel,
|
||||
DropdownMenuSeparator,
|
||||
DropdownMenuTrigger,
|
||||
} from "@/registry/new-york-v4/ui/dropdown-menu"
|
||||
} from "@/components/ui/dropdown-menu"
|
||||
import {
|
||||
SidebarMenu,
|
||||
SidebarMenuButton,
|
||||
SidebarMenuItem,
|
||||
useSidebar,
|
||||
} from "@/registry/new-york-v4/ui/sidebar"
|
||||
} from "@/components/ui/sidebar"
|
||||
|
||||
interface User {
|
||||
name: string
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
import { IconTrendingDown, IconTrendingUp } from "@tabler/icons-vue"
|
||||
|
||||
import { Badge } from "@/registry/new-york-v4/ui/badge"
|
||||
import { Badge } from "@/components/ui/badge"
|
||||
import {
|
||||
Card,
|
||||
CardAction,
|
||||
@@ -9,7 +9,7 @@ import {
|
||||
CardFooter,
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} from "@/registry/new-york-v4/ui/card"
|
||||
} from "@/components/ui/card"
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
<script setup lang="ts">
|
||||
export interface ChartConfig {
|
||||
[key: string]: {
|
||||
label: string
|
||||
color?: string
|
||||
}
|
||||
}
|
||||
|
||||
export const componentToString = () => ""
|
||||
</script>
|
||||
|
||||
<script setup lang="ts">
|
||||
defineProps<{
|
||||
config: ChartConfig
|
||||
}>()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<slot />
|
||||
</div>
|
||||
</template>
|
||||
@@ -0,0 +1,7 @@
|
||||
export type { ChartConfig } from "./ChartContainer.vue"
|
||||
export const componentToString = (config: unknown, _component: unknown, _options: unknown) => ""
|
||||
export const ChartContainer = { name: "ChartContainer" }
|
||||
export const ChartCrosshair = { name: "ChartCrosshair", template: "" }
|
||||
export const ChartLegendContent = { name: "ChartLegendContent" }
|
||||
export const ChartTooltip = { name: "ChartTooltip" }
|
||||
export const ChartTooltipContent = { name: "ChartTooltipContent" }
|
||||
@@ -0,0 +1,20 @@
|
||||
<script setup lang="ts">
|
||||
defineProps<{
|
||||
modelValue?: boolean
|
||||
'onUpdate:modelValue'?: (value: boolean) => void
|
||||
ariaLabel?: string
|
||||
disabled?: boolean
|
||||
checked?: boolean
|
||||
}>()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<input
|
||||
type="checkbox"
|
||||
:checked="modelValue || checked"
|
||||
:disabled="disabled"
|
||||
:aria-label="ariaLabel"
|
||||
@change="(e) => $emit('update:modelValue', (e.target as HTMLInputElement).checked)"
|
||||
class="h-4 w-4 rounded border-gray-300"
|
||||
/>
|
||||
</template>
|
||||
@@ -0,0 +1 @@
|
||||
export { default as Checkbox } from "./Checkbox.vue"
|
||||
@@ -0,0 +1,11 @@
|
||||
<script setup lang="ts">
|
||||
defineProps<{
|
||||
for?: string
|
||||
}>()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<label>
|
||||
<slot />
|
||||
</label>
|
||||
</template>
|
||||
@@ -0,0 +1 @@
|
||||
export { default as Label } from "./Label.vue"
|
||||
@@ -0,0 +1,181 @@
|
||||
import { ref } from "vue"
|
||||
import { kappa } from "@/services/kappa-api"
|
||||
import type {
|
||||
KappaInitiative,
|
||||
KappaUserStory,
|
||||
KappaLogbookEntry,
|
||||
KappaPlanningEntry,
|
||||
KappaBusinessRule,
|
||||
KappaRequirement,
|
||||
} from "@/types/kappa"
|
||||
|
||||
export interface SearchResult {
|
||||
type: "initiative" | "userstory" | "logbook" | "planning" | "businessrule" | "requirement"
|
||||
id: number
|
||||
title: string
|
||||
description?: string
|
||||
projectId?: number
|
||||
projectName?: string
|
||||
}
|
||||
|
||||
export function useSearch() {
|
||||
const results = ref<SearchResult[]>([])
|
||||
const loading = ref(false)
|
||||
const error = ref<string | null>(null)
|
||||
|
||||
async function search(query: string) {
|
||||
if (!query.trim()) {
|
||||
results.value = []
|
||||
return
|
||||
}
|
||||
|
||||
loading.value = true
|
||||
error.value = null
|
||||
|
||||
try {
|
||||
const allResults: SearchResult[] = []
|
||||
|
||||
const initiativeResult = await Promise.allSettled([kappa.getInitiatives()])
|
||||
if (initiativeResult[0].status === "fulfilled") {
|
||||
const data = initiativeResult[0].value as KappaInitiative[]
|
||||
const items = Array.isArray(data) ? data : (data as { results?: KappaInitiative[] }).results ?? []
|
||||
items.forEach((item: KappaInitiative) => {
|
||||
if (matchesQuery(item.name || item.initiative_name || "", query) ||
|
||||
matchesQuery(item.key || "", query) ||
|
||||
matchesQuery(item.description || "", query)) {
|
||||
allResults.push({
|
||||
type: "initiative",
|
||||
id: item.id,
|
||||
title: item.name || item.initiative_name || `Project ${item.id}`,
|
||||
description: item.description,
|
||||
projectId: item.id,
|
||||
projectName: item.name || item.initiative_name,
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const storyResult = await Promise.allSettled([kappa.getUserStories()])
|
||||
if (storyResult[0].status === "fulfilled") {
|
||||
const data = storyResult[0].value as KappaUserStory[]
|
||||
const items = Array.isArray(data) ? data : (data as { results?: KappaUserStory[] }).results ?? []
|
||||
items.forEach((item: KappaUserStory) => {
|
||||
if (matchesQuery(item.title, query) ||
|
||||
matchesQuery(item.code || "", query) ||
|
||||
matchesQuery(item.description || "", query)) {
|
||||
allResults.push({
|
||||
type: "userstory",
|
||||
id: item.id || Math.random(),
|
||||
title: item.title,
|
||||
description: item.description,
|
||||
projectId: typeof item.initiative === "number" ? item.initiative : undefined,
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const logResult = await Promise.allSettled([kappa.getLogbooks()])
|
||||
if (logResult[0].status === "fulfilled") {
|
||||
const data = logResult[0].value as KappaLogbookEntry[]
|
||||
const items = Array.isArray(data) ? data : (data as { results?: KappaLogbookEntry[] }).results ?? []
|
||||
items.forEach((item: KappaLogbookEntry) => {
|
||||
if (matchesQuery(item.description, query)) {
|
||||
allResults.push({
|
||||
type: "logbook",
|
||||
id: item.id || Math.random(),
|
||||
title: item.description.slice(0, 80),
|
||||
description: item.description,
|
||||
projectId: typeof item.initiative === "number" ? item.initiative : undefined,
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const planResult = await Promise.allSettled([kappa.getPlannings()])
|
||||
if (planResult[0].status === "fulfilled") {
|
||||
const data = planResult[0].value as KappaPlanningEntry[]
|
||||
const items = Array.isArray(data) ? data : (data as { results?: KappaPlanningEntry[] }).results ?? []
|
||||
items.forEach((item: KappaPlanningEntry) => {
|
||||
if (matchesQuery(item.description, query) ||
|
||||
matchesQuery(item.responsible || "", query)) {
|
||||
allResults.push({
|
||||
type: "planning",
|
||||
id: item.id || Math.random(),
|
||||
title: item.description.slice(0, 80),
|
||||
description: item.description,
|
||||
projectId: typeof item.initiative === "number" ? item.initiative : undefined,
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const ruleResult = await Promise.allSettled([kappa.getBusinessRules()])
|
||||
if (ruleResult[0].status === "fulfilled") {
|
||||
const data = ruleResult[0].value as KappaBusinessRule[]
|
||||
const items = Array.isArray(data) ? data : (data as { results?: KappaBusinessRule[] }).results ?? []
|
||||
items.forEach((item: KappaBusinessRule) => {
|
||||
if (matchesQuery(item.name, query) ||
|
||||
matchesQuery(item.description, query)) {
|
||||
allResults.push({
|
||||
type: "businessrule",
|
||||
id: Math.random(),
|
||||
title: item.name,
|
||||
description: item.description,
|
||||
projectId: typeof item.initiative === "number" ? item.initiative : undefined,
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const reqResult = await Promise.allSettled([kappa.getRequirements()])
|
||||
if (reqResult[0].status === "fulfilled") {
|
||||
const data = reqResult[0].value as KappaRequirement[]
|
||||
const items = Array.isArray(data) ? data : (data as { results?: KappaRequirement[] }).results ?? []
|
||||
items.forEach((item: KappaRequirement) => {
|
||||
if (matchesQuery(item.name || item.name_requirement || "", query) ||
|
||||
matchesQuery(item.description, query)) {
|
||||
allResults.push({
|
||||
type: "requirement",
|
||||
id: Math.random(),
|
||||
title: item.name || item.name_requirement || "Requirement",
|
||||
description: item.description,
|
||||
projectId: typeof item.initiative === "number" ? item.initiative : undefined,
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
results.value = allResults
|
||||
} catch (e: any) {
|
||||
error.value = e.message
|
||||
results.value = []
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
function matchesQuery(text: string, query: string): boolean {
|
||||
return text.toLowerCase().includes(query.toLowerCase())
|
||||
}
|
||||
|
||||
function clearResults() {
|
||||
results.value = []
|
||||
}
|
||||
|
||||
return {
|
||||
results,
|
||||
loading,
|
||||
error,
|
||||
search,
|
||||
clearResults,
|
||||
}
|
||||
}
|
||||
|
||||
export const typeColors: Record<SearchResult["type"], { bg: string; text: string; label: string }> = {
|
||||
initiative: { bg: "bg-blue-100 dark:bg-blue-900", text: "text-blue-700 dark:text-blue-300", label: "Project" },
|
||||
userstory: { bg: "bg-green-100 dark:bg-green-900", text: "text-green-700 dark:text-green-300", label: "User Story" },
|
||||
logbook: { bg: "bg-purple-100 dark:bg-purple-900", text: "text-purple-700 dark:text-purple-300", label: "Logbook" },
|
||||
planning: { bg: "bg-orange-100 dark:bg-orange-900", text: "text-orange-700 dark:text-orange-300", label: "Planning" },
|
||||
businessrule: { bg: "bg-red-100 dark:bg-red-900", text: "text-red-700 dark:text-red-300", label: "Rule" },
|
||||
requirement: { bg: "bg-yellow-100 dark:bg-yellow-900", text: "text-yellow-700 dark:text-yellow-300", label: "Req" },
|
||||
}
|
||||
@@ -13,6 +13,21 @@
|
||||
"templates": "Templates"
|
||||
},
|
||||
"siteHeader": {
|
||||
"title": "Dashboard"
|
||||
"title": "Dashboard",
|
||||
"search": "Search...",
|
||||
"searchDoc": "Search documentation...",
|
||||
"searching": "Searching...",
|
||||
"noResults": "No results found"
|
||||
},
|
||||
"settings": {
|
||||
"title": "Settings",
|
||||
"language": "Language",
|
||||
"theme": "Theme",
|
||||
"light": "Light",
|
||||
"dark": "Dark",
|
||||
"system": "System",
|
||||
"about": "About",
|
||||
"documentation": "Documentation",
|
||||
"logout": "Log out"
|
||||
}
|
||||
}
|
||||
+26
-11
@@ -1,18 +1,33 @@
|
||||
{
|
||||
"nav": {
|
||||
"quickCreate": "Crear proyecto",
|
||||
"dashboard": "Dashboard",
|
||||
"projects": "Projects",
|
||||
"lifecycle": "Lifecycle",
|
||||
"analytics": "Analytics",
|
||||
"team": "Team",
|
||||
"documents": "Documents",
|
||||
"dataLibrary": "Data Library",
|
||||
"reports": "Reports",
|
||||
"wordAssistant": "Word Assistant",
|
||||
"templates": "Templates"
|
||||
"dashboard": "Tablero",
|
||||
"projects": "Proyectos",
|
||||
"lifecycle": "Ciclo de vida",
|
||||
"analytics": "Analíticas",
|
||||
"team": "Equipo",
|
||||
"documents": "Documentos",
|
||||
"dataLibrary": "Biblioteca",
|
||||
"reports": "Reportes",
|
||||
"wordAssistant": "Asistente Word",
|
||||
"templates": "Plantillas"
|
||||
},
|
||||
"siteHeader": {
|
||||
"title": "Dashboard"
|
||||
"title": "Tablero",
|
||||
"search": "Buscar...",
|
||||
"searchDoc": "Buscar documentación...",
|
||||
"searching": "Buscando...",
|
||||
"noResults": "No se encontraron resultados"
|
||||
},
|
||||
"settings": {
|
||||
"title": "Configuración",
|
||||
"language": "Idioma",
|
||||
"theme": "Tema",
|
||||
"light": "Claro",
|
||||
"dark": "Oscuro",
|
||||
"system": "Sistema",
|
||||
"about": "Acerca de",
|
||||
"documentation": "Documentación",
|
||||
"logout": "Cerrar sesión"
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Scheduler tipo cron para KAPPA Hub.
|
||||
* Scheduler tipo cron para Alpha.
|
||||
*
|
||||
* Las tareas se ejecutan solo cuando la app está abierta (web app).
|
||||
* En RUMBO (Tauri) esto se vuelve un proceso en segundo plano real.
|
||||
@@ -38,7 +38,7 @@ interface ExecutionLog {
|
||||
message: string
|
||||
}
|
||||
|
||||
const db = new Dexie('kappa-hub-scheduler') as Dexie & {
|
||||
const db = new Dexie('alpha-scheduler') as Dexie & {
|
||||
rules: EntityTable<ScheduleRule, 'id'>
|
||||
logs: EntityTable<ExecutionLog, 'id'>
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ export const useProjectsStore = defineStore('projects', () => {
|
||||
loading.value = true
|
||||
error.value = null
|
||||
try {
|
||||
const data = await kappa.getInitiatives()
|
||||
const data = await kappa.getInitiatives() as KappaInitiative[] | { results?: KappaInitiative[] }
|
||||
console.log('[KAPPA] initiatives:', data)
|
||||
projects.value = Array.isArray(data) ? data : (data.results ?? [])
|
||||
} catch (e: any) {
|
||||
|
||||
@@ -44,9 +44,12 @@ export const useWorkItemsStore = defineStore('workitems', () => {
|
||||
kappa.getLogbooks(initiativeId),
|
||||
kappa.getPlannings(initiativeId),
|
||||
])
|
||||
userStories.value = Array.isArray(stories) ? stories : (stories.results ?? [])
|
||||
logbooks.value = Array.isArray(logs) ? logs : (logs.results ?? [])
|
||||
plannings.value = Array.isArray(plans) ? plans : (plans.results ?? [])
|
||||
const storiesData = stories as KappaUserStory[] | { results?: KappaUserStory[] }
|
||||
const logsData = logs as KappaLogbookEntry[] | { results?: KappaLogbookEntry[] }
|
||||
const plansData = plans as KappaPlanningEntry[] | { results?: KappaPlanningEntry[] }
|
||||
userStories.value = Array.isArray(storiesData) ? storiesData : (storiesData.results ?? [])
|
||||
logbooks.value = Array.isArray(logsData) ? logsData : (logsData.results ?? [])
|
||||
plannings.value = Array.isArray(plansData) ? plansData : (plansData.results ?? [])
|
||||
} catch (e: any) {
|
||||
error.value = e.message
|
||||
} finally {
|
||||
|
||||
@@ -25,7 +25,7 @@ async function handleLogin() {
|
||||
<span class="font-bold text-xl">A</span>
|
||||
</div>
|
||||
<CardTitle class="text-2xl font-bold tracking-tight">Alpha</CardTitle>
|
||||
<CardDescription class="text-xs mt-1">KAPPA Hub</CardDescription>
|
||||
<CardDescription class="text-xs mt-1">Alpha</CardDescription>
|
||||
</CardHeader>
|
||||
|
||||
<CardContent>
|
||||
|
||||
Reference in New Issue
Block a user