main: vibe coded app to feel like paper

Signed-off-by: nfel <nfilsaraee@gmail.com>
This commit is contained in:
2025-12-30 00:00:16 +03:30
parent acbaebb947
commit 91c149e92e
27 changed files with 901 additions and 8696 deletions
+12 -3
View File
@@ -22,7 +22,10 @@ export const albums: Album[] = [
coverImage: "/albums/echoes-of-time.jpg",
year: 2024,
genre: "Progressive Rock",
price: 12.99,
price: 350000,
tag: "Album",
format: "flac",
bitrate: "lossless",
description: "An epic journey through time and space, featuring complex polyrhythms, atmospheric keyboards, and powerful guitar solos. This concept album tells the story of humanity's relationship with time.",
songs: [
{
@@ -68,7 +71,10 @@ export const albums: Album[] = [
coverImage: "/albums/crimson-horizons.jpg",
year: 2023,
genre: "Progressive Rock",
price: 10.99,
price: 450000,
tag: "Deluxe",
format: "mp3",
bitrate: "320kbps",
description: "A darker, heavier exploration of prog rock with crushing riffs and intricate instrumental passages. Features extended improvisational sections and powerful vocals.",
songs: [
{
@@ -107,7 +113,10 @@ export const albums: Album[] = [
coverImage: "/albums/synthetic-dreams.jpg",
year: 2022,
genre: "Progressive Rock / Electronic",
price: 9.99,
price: 150000,
tag: "EP",
format: "wav",
bitrate: "lossless",
description: "A fusion of progressive rock and electronic elements, exploring the intersection of organic and synthetic sounds. Features vintage synthesizers and modern production.",
songs: [
{
+22 -10
View File
@@ -1,4 +1,4 @@
import Database from 'better-sqlite3';
import { Database } from 'bun:sqlite';
import path from 'path';
import { albums as initialAlbums } from './data';
import { Album, Purchase } from './types';
@@ -7,9 +7,9 @@ import { Album, Purchase } from './types';
const dbPath = path.join(process.cwd(), 'data', 'parsa.db');
// Initialize database
let db: Database.Database;
let db: Database;
export function getDatabase(): Database.Database {
export function getDatabase(): Database {
if (!db) {
// Create data directory if it doesn't exist
const fs = require('fs');
@@ -18,8 +18,8 @@ export function getDatabase(): Database.Database {
fs.mkdirSync(dataDir, { recursive: true });
}
db = new Database(dbPath);
db.pragma('journal_mode = WAL');
db = new Database(dbPath, { create: true });
db.exec('PRAGMA journal_mode = WAL');
initializeDatabase();
}
return db;
@@ -36,6 +36,9 @@ function initializeDatabase() {
genre TEXT NOT NULL,
description TEXT NOT NULL,
price REAL NOT NULL,
tag TEXT NOT NULL DEFAULT 'Album',
format TEXT NOT NULL DEFAULT 'mp3',
bitrate TEXT NOT NULL DEFAULT '320kbps',
songs TEXT NOT NULL,
createdAt INTEGER DEFAULT (strftime('%s', 'now')),
updatedAt INTEGER DEFAULT (strftime('%s', 'now'))
@@ -73,8 +76,8 @@ function initializeDatabase() {
function seedInitialData() {
const insert = db.prepare(`
INSERT INTO albums (id, title, coverImage, year, genre, description, price, songs)
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
INSERT INTO albums (id, title, coverImage, year, genre, description, price, tag, format, bitrate, songs)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
`);
const insertMany = db.transaction((albums: Album[]) => {
@@ -87,6 +90,9 @@ function seedInitialData() {
album.genre,
album.description,
album.price,
album.tag,
album.format,
album.bitrate,
JSON.stringify(album.songs)
);
}
@@ -119,8 +125,8 @@ export const albumDb = {
create(album: Album): void {
const db = getDatabase();
db.prepare(`
INSERT INTO albums (id, title, coverImage, year, genre, description, price, songs)
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
INSERT INTO albums (id, title, coverImage, year, genre, description, price, tag, format, bitrate, songs)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
`).run(
album.id,
album.title,
@@ -129,6 +135,9 @@ export const albumDb = {
album.genre,
album.description,
album.price,
album.tag,
album.format,
album.bitrate,
JSON.stringify(album.songs)
);
},
@@ -137,7 +146,7 @@ export const albumDb = {
const db = getDatabase();
db.prepare(`
UPDATE albums
SET title = ?, coverImage = ?, year = ?, genre = ?, description = ?, price = ?, songs = ?, updatedAt = strftime('%s', 'now')
SET title = ?, coverImage = ?, year = ?, genre = ?, description = ?, price = ?, tag = ?, format = ?, bitrate = ?, songs = ?, updatedAt = strftime('%s', 'now')
WHERE id = ?
`).run(
album.title,
@@ -146,6 +155,9 @@ export const albumDb = {
album.genre,
album.description,
album.price,
album.tag,
album.format,
album.bitrate,
JSON.stringify(album.songs),
id
);
+6
View File
@@ -1,3 +1,6 @@
export type AlbumTag = 'Album' | 'EP' | 'Demo' | 'Deluxe' | 'Single';
export type AudioFormat = 'mp3' | 'm4a' | 'flac' | 'wav';
export interface Song {
id: string;
title: string;
@@ -15,6 +18,9 @@ export interface Album {
price: number;
description: string;
songs: Song[];
tag: AlbumTag; // EP, Demo, Deluxe, etc.
format: AudioFormat; // mp3, m4a, flac, wav
bitrate: string; // e.g., "320kbps", "lossless"
}
export interface Purchase {
+8
View File
@@ -0,0 +1,8 @@
/**
* Format a price in Toman with comma separators
* @param price - Price in Toman
* @returns Formatted price string with تومان suffix
*/
export function formatPrice(price: number): string {
return `${price.toLocaleString('fa-IR')} تومان`;
}