Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 | import { ref, computed, watch, onMounted } from "vue";
import type { CartItem } from "../types/cart";
import type { TemplateType } from "../types/template";
const STORAGE_KEY = "vibery-cart";
const items = ref<CartItem[]>([]);
let initialized = false;
let watcherSetup = false;
// Load from localStorage (only call on client after mount)
function loadFromStorage() {
if (typeof window === "undefined") return;
try {
const saved = localStorage.getItem(STORAGE_KEY);
if (saved) {
items.value = JSON.parse(saved);
}
} catch (e) {
console.error("Failed to load cart from storage:", e);
items.value = [];
}
}
// Save to localStorage
function saveToStorage() {
if (typeof window === "undefined") return;
try {
localStorage.setItem(STORAGE_KEY, JSON.stringify(items.value));
} catch (e) {
console.error("Failed to save cart to storage:", e);
}
}
export function useCart() {
// Setup watcher only once
if (!watcherSetup && typeof window !== "undefined") {
watch(items, saveToStorage, { deep: true });
watcherSetup = true;
}
// Load from storage on mount (deferred to avoid hydration mismatch)
onMounted(() => {
if (!initialized) {
loadFromStorage();
initialized = true;
}
});
const count = computed(() => items.value.length);
function addItem(item: CartItem): boolean {
if (hasItem(item.name)) return false;
items.value.push(item);
return true;
}
function removeItem(name: string): void {
items.value = items.value.filter((i) => i.name !== name);
}
function clearCart(): void {
items.value = [];
}
function hasItem(name: string): boolean {
return items.value.some((i) => i.name === name);
}
function toggleItem(item: CartItem): boolean {
if (hasItem(item.name)) {
removeItem(item.name);
return false;
} else {
addItem(item);
return true;
}
}
function generateCommand(): string {
if (items.value.length === 0) return "vibery install";
return `vibery install ${items.value.map((i) => i.name).join(" ")}`;
}
function getIcon(type: TemplateType): string {
const icons: Record<TemplateType, string> = {
agent: "ph-robot",
command: "ph-terminal",
mcp: "ph-plug",
setting: "ph-gear",
hook: "ph-webhooks-logo",
skill: "ph-magic-wand",
};
return icons[type] || "ph-package";
}
return {
items: computed(() => items.value),
count,
addItem,
removeItem,
clearCart,
hasItem,
toggleItem,
generateCommand,
getIcon,
};
}
|