Initial Commit
This commit is contained in:
@@ -0,0 +1,97 @@
|
||||
/**
|
||||
* @ai-summary Database operations for user preferences
|
||||
* @ai-context Repository pattern for user preference CRUD operations
|
||||
*/
|
||||
|
||||
import { Pool } from 'pg';
|
||||
import { UserPreferences, CreateUserPreferencesRequest, UpdateUserPreferencesRequest } from '../user-preferences.types';
|
||||
|
||||
export class UserPreferencesRepository {
|
||||
constructor(private db: Pool) {}
|
||||
|
||||
async findByUserId(userId: string): Promise<UserPreferences | null> {
|
||||
const query = `
|
||||
SELECT id, user_id, unit_system, currency_code, time_zone, created_at, updated_at
|
||||
FROM user_preferences
|
||||
WHERE user_id = $1
|
||||
`;
|
||||
|
||||
const result = await this.db.query(query, [userId]);
|
||||
return result.rows.length > 0 ? this.mapRow(result.rows[0]) : null;
|
||||
}
|
||||
|
||||
async create(data: CreateUserPreferencesRequest): Promise<UserPreferences> {
|
||||
const query = `
|
||||
INSERT INTO user_preferences (user_id, unit_system, currency_code, time_zone)
|
||||
VALUES ($1, $2, $3, $4)
|
||||
RETURNING *
|
||||
`;
|
||||
|
||||
const values = [
|
||||
data.userId,
|
||||
data.unitSystem || 'imperial',
|
||||
(data as any).currencyCode || 'USD',
|
||||
(data as any).timeZone || 'UTC'
|
||||
];
|
||||
|
||||
const result = await this.db.query(query, values);
|
||||
return this.mapRow(result.rows[0]);
|
||||
}
|
||||
|
||||
async update(userId: string, data: UpdateUserPreferencesRequest): Promise<UserPreferences | null> {
|
||||
const fields = [];
|
||||
const values = [];
|
||||
let paramCount = 1;
|
||||
|
||||
if (data.unitSystem !== undefined) {
|
||||
fields.push(`unit_system = $${paramCount++}`);
|
||||
values.push(data.unitSystem);
|
||||
}
|
||||
if ((data as any).currencyCode !== undefined) {
|
||||
fields.push(`currency_code = $${paramCount++}`);
|
||||
values.push((data as any).currencyCode);
|
||||
}
|
||||
if ((data as any).timeZone !== undefined) {
|
||||
fields.push(`time_zone = $${paramCount++}`);
|
||||
values.push((data as any).timeZone);
|
||||
}
|
||||
|
||||
if (fields.length === 0) {
|
||||
return this.findByUserId(userId);
|
||||
}
|
||||
|
||||
const query = `
|
||||
UPDATE user_preferences
|
||||
SET ${fields.join(', ')}, updated_at = CURRENT_TIMESTAMP
|
||||
WHERE user_id = $${paramCount}
|
||||
RETURNING *
|
||||
`;
|
||||
|
||||
values.push(userId);
|
||||
const result = await this.db.query(query, values);
|
||||
return result.rows.length > 0 ? this.mapRow(result.rows[0]) : null;
|
||||
}
|
||||
|
||||
async upsert(data: CreateUserPreferencesRequest): Promise<UserPreferences> {
|
||||
const existing = await this.findByUserId(data.userId);
|
||||
|
||||
if (existing) {
|
||||
const updated = await this.update(data.userId, { unitSystem: data.unitSystem });
|
||||
return updated!;
|
||||
}
|
||||
|
||||
return this.create(data);
|
||||
}
|
||||
|
||||
private mapRow(row: any): UserPreferences {
|
||||
return {
|
||||
id: row.id,
|
||||
userId: row.user_id,
|
||||
unitSystem: row.unit_system,
|
||||
currencyCode: row.currency_code || 'USD',
|
||||
timeZone: row.time_zone || 'UTC',
|
||||
createdAt: row.created_at,
|
||||
updatedAt: row.updated_at,
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
-- Create user_preferences table for storing user settings
|
||||
CREATE TYPE unit_system AS ENUM ('imperial', 'metric');
|
||||
|
||||
CREATE TABLE IF NOT EXISTS user_preferences (
|
||||
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||
user_id VARCHAR(255) UNIQUE NOT NULL,
|
||||
unit_system unit_system NOT NULL DEFAULT 'imperial',
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
-- Create indexes
|
||||
CREATE INDEX idx_user_preferences_user_id ON user_preferences(user_id);
|
||||
|
||||
-- Add trigger for updated_at
|
||||
CREATE TRIGGER update_user_preferences_updated_at
|
||||
BEFORE UPDATE ON user_preferences
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION update_updated_at_column();
|
||||
@@ -0,0 +1,7 @@
|
||||
-- Add currency_code and time_zone to user_preferences
|
||||
ALTER TABLE user_preferences
|
||||
ADD COLUMN IF NOT EXISTS currency_code VARCHAR(3) DEFAULT 'USD',
|
||||
ADD COLUMN IF NOT EXISTS time_zone VARCHAR(100) DEFAULT 'UTC';
|
||||
|
||||
-- Optional: basic length/format checks can be enforced at application layer
|
||||
|
||||
37
backend/src/core/user-preferences/user-preferences.types.ts
Normal file
37
backend/src/core/user-preferences/user-preferences.types.ts
Normal file
@@ -0,0 +1,37 @@
|
||||
/**
|
||||
* @ai-summary Type definitions for user preferences system
|
||||
* @ai-context Manages user settings including unit preferences
|
||||
*/
|
||||
|
||||
export type UnitSystem = 'imperial' | 'metric';
|
||||
|
||||
export interface UserPreferences {
|
||||
id: string;
|
||||
userId: string;
|
||||
unitSystem: UnitSystem;
|
||||
currencyCode: string;
|
||||
timeZone: string;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
}
|
||||
|
||||
export interface CreateUserPreferencesRequest {
|
||||
userId: string;
|
||||
unitSystem?: UnitSystem;
|
||||
}
|
||||
|
||||
export interface UpdateUserPreferencesRequest {
|
||||
unitSystem?: UnitSystem;
|
||||
currencyCode?: string;
|
||||
timeZone?: string;
|
||||
}
|
||||
|
||||
export interface UserPreferencesResponse {
|
||||
id: string;
|
||||
userId: string;
|
||||
unitSystem: UnitSystem;
|
||||
currencyCode: string;
|
||||
timeZone: string;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
Reference in New Issue
Block a user