first commit

This commit is contained in:
Beyhan Oğur
2026-04-26 22:18:17 +03:00
commit 7b2b27a42c
1660 changed files with 123050 additions and 0 deletions

18
app/stores/banner.ts Normal file
View File

@@ -0,0 +1,18 @@
import { defineStore } from 'pinia';
import type { Banner } from '~~/types/banner';
interface BannerState {
banner: Banner[];
}
export const useBannerStore = defineStore('banner', {
state: (): BannerState => ({
banner: [],
}),
actions: {
setBanner(newBanner: Banner[]): void {
this.banner = newBanner;
}
}
});

177
app/stores/cart.ts Normal file
View File

@@ -0,0 +1,177 @@
import { defineStore } from 'pinia';
import type { Product } from '~~/types/product';
export interface CartItem {
product: Product;
quantity: number;
}
export type CouponType = 'percent' | 'fixed';
export interface CartCoupon {
code: string;
type: CouponType;
value: number;
description?: string;
minSubtotal?: number;
}
interface CartState {
items: CartItem[];
coupon: CartCoupon | null;
}
const CART_STORAGE_KEY = 'nuxt-shop-cart-v1';
const AVAILABLE_COUPONS: CartCoupon[] = [
{
code: 'SALE10',
type: 'percent',
value: 10,
description: '10% indirim',
},
{
code: 'WELCOME50',
type: 'fixed',
value: 50,
description: '50 TL indirim',
minSubtotal: 300,
},
];
export const useCartStore = defineStore('cart', {
state: (): CartState => ({
items: [],
coupon: null,
}),
getters: {
totalQuantity: (state): number =>
state.items.reduce((total, item) => total + item.quantity, 0),
subtotal: (state): number =>
state.items.reduce(
(total, item) => total + item.product.price * item.quantity,
0
),
discountAmount(): number {
if (!this.coupon) return 0;
if (this.coupon.minSubtotal && this.subtotal < this.coupon.minSubtotal) {
return 0;
}
const rawDiscount =
this.coupon.type === 'percent'
? (this.subtotal * this.coupon.value) / 100
: this.coupon.value;
return Math.min(rawDiscount, this.subtotal);
},
total(): number {
return Math.max(this.subtotal - this.discountAmount, 0);
},
totalPrice(): number {
return this.total;
},
getItem:
(state) =>
(slug: string): CartItem | undefined =>
state.items.find((item) => item.product.slug === slug),
},
actions: {
addItem(product: Product, quantity = 1): void {
if (!Number.isFinite(quantity) || quantity <= 0) {
return;
}
const existingItem = this.items.find(
(item) => item.product.slug === product.slug
);
if (existingItem) {
existingItem.quantity += quantity;
existingItem.product = product;
return;
}
this.items.push({ product, quantity });
},
setItemQuantity(slug: string, quantity: number): void {
if (!Number.isFinite(quantity)) {
return;
}
const item = this.items.find((entry) => entry.product.slug === slug);
if (!item) {
return;
}
if (quantity <= 0) {
this.items = this.items.filter(
(entry) => entry.product.slug !== slug
);
return;
}
item.quantity = Math.floor(quantity);
},
removeItem(slug: string): void {
this.items = this.items.filter(
(item) => item.product.slug !== slug
);
},
clearCart(): void {
this.items = [];
this.coupon = null;
},
setItems(items: CartItem[]): void {
this.items = items;
},
applyCouponCode(code: string): boolean {
const normalizedCode = code.trim().toUpperCase();
if (!normalizedCode) return false;
const coupon = AVAILABLE_COUPONS.find(
(entry) => entry.code === normalizedCode
);
if (!coupon) return false;
if (coupon.minSubtotal && this.subtotal < coupon.minSubtotal) {
return false;
}
this.coupon = coupon;
return true;
},
clearCoupon(): void {
this.coupon = null;
},
setCoupon(coupon: CartCoupon | null): void {
this.coupon = coupon;
},
hydrateFromStorage(payload: string | null): void {
if (!payload) return;
try {
const parsed = JSON.parse(payload) as {
items?: CartItem[];
coupon?: CartCoupon | null;
};
if (Array.isArray(parsed.items)) {
this.items = parsed.items.filter(
(entry) =>
entry &&
entry.product &&
typeof entry.product.slug === 'string' &&
typeof entry.quantity === 'number'
);
}
if (parsed.coupon && typeof parsed.coupon.code === 'string') {
this.coupon = parsed.coupon;
}
} catch {
// Ignore invalid storage payloads
}
},
toStoragePayload(): string {
return JSON.stringify({
items: this.items,
coupon: this.coupon,
});
},
getStorageKey(): string {
return CART_STORAGE_KEY;
},
},
});

17
app/stores/productTree.ts Normal file
View File

@@ -0,0 +1,17 @@
import { defineStore } from 'pinia';
import type { ProductTree } from '~~/types/banner';
interface ProductTreeState {
productTree: ProductTree[];
}
export const useProductTreeStore = defineStore('productTree', {
state: (): ProductTreeState => ({
productTree: [],
}),
actions: {
setProductTree(newProductTree: ProductTree[]): void {
this.productTree = newProductTree;
}
}
});

17
app/stores/setting.ts Normal file
View File

@@ -0,0 +1,17 @@
import { defineStore } from 'pinia';
import type { Setting } from '~~/types/setting';
interface SettingState {
settings: Setting | null;
}
export const useSettingStore = defineStore('setting', {
state: (): SettingState => ({
settings: null,
}),
actions: {
setSettings(newSettings: Setting | null): void {
this.settings = newSettings;
}
}
});