111 lines
3.1 KiB
TypeScript
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;
|
|
}
|
|
}
|