rename proyecto a Alpha, refactor imports a components/ui, fix types en stores

This commit is contained in:
Ricardo Gonzalez
2026-05-23 17:38:15 -05:00
parent 002d8f06d3
commit 72662852bf
24 changed files with 347 additions and 59 deletions
+21
View File
@@ -13,6 +13,7 @@
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"dexie": "^4.0.4",
"dnd-kit-vue": "^0.0.2",
"lucide-vue-next": "^1.0.0",
"pinia": "^2.1.7",
"reka-ui": "^2.9.8",
@@ -89,6 +90,16 @@
"@babel/types": ["@babel/types@7.29.0", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.28.5" } }, "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A=="],
"@dnd-kit/abstract": ["@dnd-kit/abstract@0.1.21", "", { "dependencies": { "@dnd-kit/geometry": "^0.1.21", "@dnd-kit/state": "^0.1.21", "tslib": "^2.6.2" } }, "sha512-6sJut6/D21xPIK8EFMu+JJeF+fBCOmQKN1BRpeUYFi5m9P1CJpTYbBwfI107h7PHObI6a5bsckiKkRpF2orHpw=="],
"@dnd-kit/collision": ["@dnd-kit/collision@0.1.21", "", { "dependencies": { "@dnd-kit/abstract": "^0.1.21", "@dnd-kit/geometry": "^0.1.21", "tslib": "^2.6.2" } }, "sha512-9AJ4NbuwGDexxMCZXZyKdNQhbAe93p6C6IezQaDaWmdCqZHMHmC3+ul7pGefBQfOooSarGwIf8Bn182o9SMa1A=="],
"@dnd-kit/dom": ["@dnd-kit/dom@0.1.21", "", { "dependencies": { "@dnd-kit/abstract": "^0.1.21", "@dnd-kit/collision": "^0.1.21", "@dnd-kit/geometry": "^0.1.21", "@dnd-kit/state": "^0.1.21", "tslib": "^2.6.2" } }, "sha512-6UDc1y2Y3oLQKArGlgCrZxz5pdEjRSiQujXOn5JdbuWvKqTdUR5RTYDeicr+y2sVm3liXjTqs3WlUoV+eqhqUQ=="],
"@dnd-kit/geometry": ["@dnd-kit/geometry@0.1.21", "", { "dependencies": { "@dnd-kit/state": "^0.1.21", "tslib": "^2.6.2" } }, "sha512-Tir97wNJbopN2HgkD7AjAcoB3vvrVuUHvwdPALmNDUH0fWR637c4MKQ66YjjZAbUEAR8KL6mlDiHH4MzTLd7CQ=="],
"@dnd-kit/state": ["@dnd-kit/state@0.1.21", "", { "dependencies": { "@preact/signals-core": "^1.10.0", "tslib": "^2.6.2" } }, "sha512-pdhntEPvn/QttcF295bOJpWiLsRqA/Iczh1ODOJUxGiR+E4GkYVz9VapNNm9gDq6ST0tr/e1Q2xBztUHlJqQgA=="],
"@dotenvx/dotenvx": ["@dotenvx/dotenvx@1.67.0", "", { "dependencies": { "commander": "^11.1.0", "dotenv": "^17.2.1", "eciesjs": "^0.4.10", "enquirer": "^2.4.1", "execa": "^5.1.1", "fdir": "^6.2.0", "ignore": "^5.3.0", "object-treeify": "1.1.33", "picomatch": "^4.0.4", "which": "^4.0.0", "yocto-spinner": "^1.1.0" }, "bin": { "dotenvx": "src/cli/dotenvx.js" } }, "sha512-KBfIx5OrAG6giqSkHCkQWynZmT47XkSTuuYIcvjHxlKoVRlYbxNrJmyIPaefnszU8MCvMwrrB+viJQzPqzgpcg=="],
"@ecies/ciphers": ["@ecies/ciphers@0.2.6", "", { "peerDependencies": { "@noble/ciphers": "^1.0.0" } }, "sha512-patgsRPKGkhhoBjETV4XxD0En4ui5fbX0hzayqI3M8tvNMGUoUvmyYAIWwlxBc1KX5cturfqByYdj5bYGRpN9g=="],
@@ -213,6 +224,8 @@
"@nodelib/fs.walk": ["@nodelib/fs.walk@1.2.8", "", { "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" } }, "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg=="],
"@preact/signals-core": ["@preact/signals-core@1.14.2", "", {}, "sha512-RZHdBj9ZF4n40Rp4jS052EHHjBWf96P9oNdXPfhQTovCuWY9iQn3Gq+gOTJSgBO9A/JBuPfMOWsSX/lIU9Pc/A=="],
"@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.60.4", "", { "os": "android", "cpu": "arm" }, "sha512-F5QXMSiFebS9hKZj02XhWLLnRpJ3B3AROP0tWbFBSj+6kCbg5m9j5JoHKd4mmSVy5mS/IMQloYgYxCuJC0fxEQ=="],
"@rollup/rollup-android-arm64": ["@rollup/rollup-android-arm64@4.60.4", "", { "os": "android", "cpu": "arm64" }, "sha512-GxxTKApUpzRhof7poWvCJHRF51C67u1R7D6DiluBE8wKU1u5GWE8t+v81JvJYtbawoBFX1hLv5Ei4eVjkWokaw=="],
@@ -501,6 +514,8 @@
"diff": ["diff@8.0.4", "", {}, "sha512-DPi0FmjiSU5EvQV0++GFDOJ9ASQUVFh5kD+OzOnYdi7n3Wpm9hWWGfB/O2blfHcMVTL5WkQXSnRiK9makhrcnw=="],
"dnd-kit-vue": ["dnd-kit-vue@0.0.2", "", { "dependencies": { "@dnd-kit/abstract": "^0.1.19", "@dnd-kit/dom": "^0.1.19", "@dnd-kit/state": "^0.1.19", "@vueuse/core": "^13.4.0", "reka-ui": "^2.3.1" }, "peerDependencies": { "vue": "^3.3.0" } }, "sha512-2ZQfqTulZI7vqFiYscV7VMQRXSEryjanlaCY5BvkDf5i+whEAvOKSckyBa6SK8LCPaF5f/IIcUhfh6TnbaWq3A=="],
"dom-serializer": ["dom-serializer@2.0.0", "", { "dependencies": { "domelementtype": "^2.3.0", "domhandler": "^5.0.2", "entities": "^4.2.0" } }, "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg=="],
"domelementtype": ["domelementtype@2.3.0", "", {}, "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw=="],
@@ -1117,6 +1132,8 @@
"css/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="],
"dnd-kit-vue/@vueuse/core": ["@vueuse/core@13.9.0", "", { "dependencies": { "@types/web-bluetooth": "^0.0.21", "@vueuse/metadata": "13.9.0", "@vueuse/shared": "13.9.0" }, "peerDependencies": { "vue": "^3.5.0" } }, "sha512-ts3regBQyURfCE2BcytLqzm8+MmLlo5Ln/KLoxDVcsZ2gzIwVNnQpQOL/UKV8alUqjSZOlpFZcRNsLRqj+OzyA=="],
"dom-serializer/entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="],
"eslint/ajv": ["ajv@6.15.0", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw=="],
@@ -1155,6 +1172,10 @@
"cross-spawn/which/isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="],
"dnd-kit-vue/@vueuse/core/@vueuse/metadata": ["@vueuse/metadata@13.9.0", "", {}, "sha512-1AFRvuiGphfF7yWixZa0KwjYH8ulyjDCC0aFgrGRz8+P4kvDFSdXLVfTk5xAN9wEuD1J6z4/myMoYbnHoX07zg=="],
"dnd-kit-vue/@vueuse/core/@vueuse/shared": ["@vueuse/shared@13.9.0", "", { "peerDependencies": { "vue": "^3.5.0" } }, "sha512-e89uuTLMh0U5cZ9iDpEI2senqPGfbPRTHM/0AaQkcxnpqjkZqDYP8rpfm7edOz8s+pOCOROEy1PIveSW8+fL5g=="],
"eslint/ajv/json-schema-traverse": ["json-schema-traverse@0.4.1", "", {}, "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="],
"eslint/minimatch/brace-expansion": ["brace-expansion@5.0.6", "", { "dependencies": { "balanced-match": "^4.0.2" } }, "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g=="],
+1 -1
View File
@@ -3,7 +3,7 @@
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Alpha — KAPPA Hub</title>
<title>Alpha</title>
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
+2 -1
View File
@@ -1,5 +1,5 @@
{
"name": "kappa-hub",
"name": "alpha",
"version": "0.1.0",
"private": true,
"type": "module",
@@ -18,6 +18,7 @@
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"dexie": "^4.0.4",
"dnd-kit-vue": "^0.0.2",
"lucide-vue-next": "^1.0.0",
"pinia": "^2.1.7",
"reka-ui": "^2.9.8",
+1 -1
View File
@@ -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>
+4 -16
View File
@@ -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',
+10 -9
View File
@@ -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 -1
View File
@@ -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>
+1 -1
View File
@@ -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 }>()
+3 -3
View File
@@ -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
+2 -2
View File
@@ -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>
+7
View File
@@ -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" }
+20
View File
@@ -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>
+1
View File
@@ -0,0 +1 @@
export { default as Checkbox } from "./Checkbox.vue"
+11
View File
@@ -0,0 +1,11 @@
<script setup lang="ts">
defineProps<{
for?: string
}>()
</script>
<template>
<label>
<slot />
</label>
</template>
+1
View File
@@ -0,0 +1 @@
export { default as Label } from "./Label.vue"
+181
View File
@@ -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" },
}
+16 -1
View File
@@ -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
View File
@@ -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"
}
}
+2 -2
View File
@@ -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'>
}
+1 -1
View File
@@ -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) {
+6 -3
View File
@@ -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 {
+1 -1
View File
@@ -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>