stock-portfolio_byQwen3.6/src/actions/asset.ts

111 lines
3.1 KiB
TypeScript

'use server';
import { db } from '@/db';
import { assets, assetTypeEnum } from '@/db/schema';
import { eq } from 'drizzle-orm';
import { revalidatePath } from 'next/cache';
import { z } from 'zod';
const createAssetSchema = z.object({
symbol: z.string().min(1, 'Symbol is required'),
type: z.enum(['STOCK', 'CRYPTO', 'CASH']),
exchange: z.string().optional(),
baseCurrency: z.string().min(2).max(10),
});
export async function createAsset(params: z.infer<typeof createAssetSchema>) {
const validation = createAssetSchema.safeParse(params);
if (!validation.success) {
return { success: false, error: validation.error.issues[0].message };
}
try {
const [asset] = await db.insert(assets).values(params).returning();
return { success: true, data: asset };
} catch (error: unknown) {
if (
error &&
typeof error === 'object' &&
'code' in error &&
(error as { code: string }).code === '23505'
) {
return { success: false, error: 'Asset with this symbol already exists' };
}
throw error;
}
}
export async function getAssets() {
return db.select().from(assets);
}
const updateAssetSchema = z.object({
id: z.string().uuid(),
symbol: z.string().min(1, 'Symbol is required').optional(),
exchange: z.string().optional(),
type: z.enum(['STOCK', 'CRYPTO', 'CASH']).optional(),
baseCurrency: z.string().min(2).max(10).optional(),
});
export async function updateAsset(params: z.infer<typeof updateAssetSchema>) {
const validation = updateAssetSchema.safeParse(params);
if (!validation.success) {
return { success: false, error: validation.error.issues[0].message };
}
const { id, ...updates } = validation.data;
const filteredUpdates = Object.fromEntries(
Object.entries(updates).filter(([, v]) => v !== undefined)
);
if (Object.keys(filteredUpdates).length === 0) {
return { success: false, error: 'No fields to update' };
}
try {
await db.update(assets).set(filteredUpdates).where(eq(assets.id, id));
revalidatePath('/dashboard');
return { success: true };
} catch (error: unknown) {
if (
error &&
typeof error === 'object' &&
'code' in error &&
(error as { code: string }).code === '23505'
) {
return { success: false, error: 'Asset with this symbol already exists' };
}
throw error;
}
}
export async function deleteAsset(id: string) {
try {
await db.delete(assets).where(eq(assets.id, id));
revalidatePath('/dashboard');
return { success: true };
} catch (error: unknown) {
throw error;
}
}
const updatePriceSchema = z.object({
assetId: z.string().min(1, 'Asset ID is required'),
newPrice: z.string().min(1, 'Price is required'),
});
export async function updateAssetPrice(params: z.infer<typeof updatePriceSchema>) {
const validation = updatePriceSchema.safeParse(params);
if (!validation.success) {
return { success: false, error: validation.error.issues[0].message };
}
try {
await db.update(assets).set({ latestPrice: params.newPrice }).where(eq(assets.id, params.assetId));
revalidatePath('/dashboard');
return { success: true };
} catch (error: unknown) {
throw error;
}
}