mobileapp / src /db /schema.ts
Antaram Dev Bot
feat: complete ANTARAM.ORG ride-sharing app frontend
5c876be
import {
sqliteTable,
text,
integer,
real,
primaryKey,
} from 'drizzle-orm/sqlite-core';
import { sql } from 'drizzle-orm';
// ─── currentUser ────────────────────────────────────────────────────────────────
// Stores the authenticated user's profile data. A single row is expected.
export const currentUser = sqliteTable('current_user', {
id: text('id').primaryKey(),
phone: text('phone').notNull(),
fullName: text('full_name').notNull(),
email: text('email'),
avatarUrl: text('avatar_url'),
gender: text('gender', { enum: ['male', 'female', 'other'] }),
homeAddress: text('home_address'),
workAddress: text('work_address'),
preferredLanguage: text('preferred_language').default('en'),
rating: real('rating').default(0),
totalRides: integer('total_rides').default(0),
verified: integer('verified', { mode: 'boolean' }).default(false),
createdAt: text('created_at')
.notNull()
.default(sql`(datetime('now'))`),
updatedAt: text('updated_at')
.notNull()
.default(sql`(datetime('now'))`),
});
// ─── savedLocations ─────────────────────────────────────────────────────────────
export const savedLocations = sqliteTable('saved_locations', {
id: text('id').primaryKey(),
userId: text('user_id')
.notNull()
.references(() => currentUser.id, { onDelete: 'cascade' }),
name: text('name').notNull(),
address: text('address').notNull(),
latitude: real('latitude').notNull(),
longitude: real('longitude').notNull(),
type: text('type', {
enum: ['home', 'work', 'favorite', 'recent'],
}).default('favorite'),
createdAt: text('created_at')
.notNull()
.default(sql`(datetime('now'))`),
});
// ─── rides ──────────────────────────────────────────────────────────────────────
export const rides = sqliteTable('rides', {
id: text('id').primaryKey(),
userId: text('user_id')
.notNull()
.references(() => currentUser.id, { onDelete: 'cascade' }),
originAddress: text('origin_address').notNull(),
originLatitude: real('origin_latitude').notNull(),
originLongitude: real('origin_longitude').notNull(),
destinationAddress: text('destination_address').notNull(),
destinationLatitude: real('destination_latitude').notNull(),
destinationLongitude: real('destination_longitude').notNull(),
routePolyline: text('route_polyline'),
scheduledTime: text('scheduled_time'),
status: text('status', {
enum: [
'searching',
'matched',
'in_progress',
'completed',
'cancelled',
],
})
.notNull()
.default('searching'),
seatPrice: real('seat_price'),
totalDistance: real('total_distance'), // in km
estimatedDuration: integer('estimated_duration'), // in minutes
createdAt: text('created_at')
.notNull()
.default(sql`(datetime('now'))`),
updatedAt: text('updated_at')
.notNull()
.default(sql`(datetime('now'))`),
});
// ─── matches ────────────────────────────────────────────────────────────────────
export const matches = sqliteTable('matches', {
id: text('id').primaryKey(),
rideId: text('ride_id')
.notNull()
.references(() => rides.id, { onDelete: 'cascade' }),
matchedUserId: text('matched_user_id').notNull(),
matchedUserFullName: text('matched_user_full_name').notNull(),
matchedUserAvatar: text('matched_user_avatar'),
matchedUserRating: real('matched_user_rating').default(0),
pickupPoint: text('pickup_point'),
pickupLatitude: real('pickup_latitude'),
pickupLongitude: real('pickup_longitude'),
dropoffPoint: text('dropoff_point'),
dropoffLatitude: real('dropoff_latitude'),
dropoffLongitude: real('dropoff_longitude'),
status: text('status', {
enum: ['pending', 'accepted', 'rejected', 'completed', 'cancelled'],
})
.notNull()
.default('pending'),
createdAt: text('created_at')
.notNull()
.default(sql`(datetime('now'))`),
updatedAt: text('updated_at')
.notNull()
.default(sql`(datetime('now'))`),
});
// ─── conversations ──────────────────────────────────────────────────────────────
export const conversations = sqliteTable('conversations', {
id: text('id').primaryKey(),
participant1Id: text('participant_1_id').notNull(),
participant2Id: text('participant_2_id').notNull(),
lastMessage: text('last_message'),
lastMessageAt: text('last_message_at'),
unreadCount: integer('unread_count').default(0),
createdAt: text('created_at')
.notNull()
.default(sql`(datetime('now'))`),
updatedAt: text('updated_at')
.notNull()
.default(sql`(datetime('now'))`),
});
// ─── messages ───────────────────────────────────────────────────────────────────
export const messages = sqliteTable('messages', {
id: text('id').primaryKey(),
conversationId: text('conversation_id')
.notNull()
.references(() => conversations.id, { onDelete: 'cascade' }),
senderId: text('sender_id').notNull(),
content: text('content').notNull(),
type: text('type', { enum: ['text', 'image', 'location', 'system'] })
.notNull()
.default('text'),
status: text('status', {
enum: ['sending', 'sent', 'delivered', 'read', 'failed'],
})
.notNull()
.default('sending'),
createdAt: text('created_at')
.notNull()
.default(sql`(datetime('now'))`),
});
// ─── friends ────────────────────────────────────────────────────────────────────
export const friends = sqliteTable('friends', {
id: text('id').primaryKey(),
userId: text('user_id')
.notNull()
.references(() => currentUser.id, { onDelete: 'cascade' }),
friendId: text('friend_id').notNull(),
friendFullName: text('friend_full_name').notNull(),
friendAvatar: text('friend_avatar'),
friendPhone: text('friend_phone'),
status: text('status', {
enum: ['pending', 'accepted', 'blocked'],
})
.notNull()
.default('pending'),
createdAt: text('created_at')
.notNull()
.default(sql`(datetime('now'))`),
});
// ─── ratings ────────────────────────────────────────────────────────────────────
export const ratings = sqliteTable('ratings', {
id: text('id').primaryKey(),
rideId: text('ride_id')
.notNull()
.references(() => rides.id, { onDelete: 'cascade' }),
fromUserId: text('from_user_id').notNull(),
toUserId: text('to_user_id').notNull(),
score: integer('score').notNull(), // 1-5
review: text('review'),
createdAt: text('created_at')
.notNull()
.default(sql`(datetime('now'))`),
});
// ─── notifications ──────────────────────────────────────────────────────────────
export const notifications = sqliteTable('notifications', {
id: text('id').primaryKey(),
userId: text('user_id')
.notNull()
.references(() => currentUser.id, { onDelete: 'cascade' }),
type: text('type', {
enum: [
'ride_matched',
'ride_cancelled',
'ride_completed',
'message',
'friend_request',
'system',
],
}).notNull(),
title: text('title').notNull(),
body: text('body').notNull(),
data: text('data'), // JSON string for extra payload
read: integer('read', { mode: 'boolean' }).default(false),
createdAt: text('created_at')
.notNull()
.default(sql`(datetime('now'))`),
});
// ─── searchHistory ──────────────────────────────────────────────────────────────
export const searchHistory = sqliteTable('search_history', {
id: text('id').primaryKey(),
userId: text('user_id')
.notNull()
.references(() => currentUser.id, { onDelete: 'cascade' }),
query: text('query').notNull(),
address: text('address').notNull(),
latitude: real('latitude').notNull(),
longitude: real('longitude').notNull(),
searchedAt: text('searched_at')
.notNull()
.default(sql`(datetime('now'))`),
});
// ─── appState ───────────────────────────────────────────────────────────────────
// Key-value store for application-level preferences and flags.
export const appState = sqliteTable('app_state', {
key: text('key').primaryKey(),
value: text('value').notNull(),
updatedAt: text('updated_at')
.notNull()
.default(sql`(datetime('now'))`),
});