-
Notifications
You must be signed in to change notification settings - Fork 25
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
7 changed files
with
371 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
import ErrorHandler from "../../../utils/ErrorHandler"; | ||
import { supabase } from "../../../utils/supabase"; | ||
|
||
import Event, { DBEvent } from '../Entities/Event'; | ||
import EventService from "../Services/EventService"; | ||
|
||
|
||
const EVENT_TABLE_NAME = "events" | ||
|
||
|
||
export default class EventController { | ||
|
||
|
||
/** | ||
* Get an array of events | ||
* | ||
* @usage eventController.getEvents(<PARAMS>).then( | ||
* (events: Array<Events>) => { ... } | ||
* ) | ||
* | ||
* @param {string} fields - The columns to retrieve (comma-separated) | ||
* @param {string} orderBy - Which field to order by (leave blank if not needed) | ||
* @param {boolean} orderDescending - Whether to order in descending order (defaults to false) | ||
* @param {number} rangeStart - Starting index of fetch (defaults to 0) | ||
* @param {number} rangeEnd - Ending index of fetch (defaults to 100) | ||
* | ||
* @returns {Array<Event>} - Array of events | ||
* | ||
* @see [https://supabase.com/docs/reference/javascript/order] | ||
* @see [https://supabase.com/docs/reference/javascript/range] | ||
* | ||
* @author Henry C. (@yeahlowflicker) | ||
*/ | ||
public async getEvents( | ||
fields: string, | ||
orderBy?: string, | ||
orderDescending?: boolean, | ||
rangeStart?: number, | ||
rangeEnd?: number | ||
) : Promise<Array<Event> | null> { | ||
|
||
const query = supabase | ||
.from(EVENT_TABLE_NAME) | ||
.select(fields) | ||
.returns<Array<DBEvent>>() | ||
|
||
if (orderBy) | ||
query.order(orderBy, { ascending: !orderDescending }) | ||
|
||
if (rangeStart !== undefined && rangeEnd !== undefined) | ||
query.range(rangeStart, rangeEnd) | ||
|
||
const { data, error } = await query | ||
|
||
// Error handling | ||
if (error) { | ||
ErrorHandler.handleSupabaseError(error) | ||
return null | ||
} | ||
|
||
// Initialize result array | ||
const events : Array<Event> = [] | ||
|
||
|
||
// For each found DBEvent, convert to Event and append to result array | ||
data.forEach((record: DBEvent) => { | ||
events.push( | ||
EventService.parseEvent(record) | ||
) | ||
}) | ||
|
||
return events | ||
} | ||
|
||
|
||
|
||
/** | ||
* Find a single event by ID | ||
* | ||
* @usage eventController.FindEventByID(<PARAMS>).then( | ||
* (event: Event) => { ... } | ||
* ) | ||
* | ||
* @param {string} eventID - Target event ID | ||
* @param {string} fields - The columns to retrieve | ||
* | ||
* @returns {Event} - The target event entity (null if not found) | ||
* | ||
* @author Henry C. (@yeahlowflicker) | ||
*/ | ||
public async findEventByID(eventID: string, fields?: string) : Promise<Event | null> { | ||
|
||
const { data, error } = await supabase | ||
.from(EVENT_TABLE_NAME) | ||
.select(fields) | ||
.eq("id", eventID) | ||
.returns<DBEvent>() | ||
.limit(1) | ||
.single() | ||
|
||
// Error handling | ||
if (error) { | ||
ErrorHandler.handleSupabaseError(error) | ||
return null | ||
} | ||
|
||
if (!data) | ||
return null | ||
|
||
// Type conversion: DBEvent -> Event | ||
const event : Event = EventService.parseEvent(data) | ||
|
||
return event | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import { Database } from "../../../utils/database.types"; | ||
|
||
/** | ||
* This is a dummy-type inherited from the generated Supabase type | ||
*/ | ||
export type DBEvent = Database['public']['Tables']['events']['Row']; | ||
|
||
|
||
export default class Event { | ||
|
||
public id: number = 0; | ||
public name: string = ""; | ||
public type: number = 0; | ||
public description: string = ""; | ||
public startTime: string = ""; | ||
public endTime: string = ""; | ||
public location: string = ""; | ||
public fee: number = 0; | ||
public userID: string = ""; | ||
public createdAt: string = ""; | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
import Event, { DBEvent } from "../Entities/Event"; | ||
|
||
const EventService = { | ||
|
||
parseEvent(record: DBEvent) : Event { | ||
if (!record || typeof record !== 'object') | ||
throw new Error('Invalid record provided') | ||
|
||
if (!record.id) | ||
throw new Error('id is a required field') | ||
|
||
const event = new Event() | ||
|
||
event.id = record.id | ||
event.name = record.name ?? "" | ||
event.type = typeof record.type === 'number' ? record.type : 0 | ||
event.description = record.description ?? "" | ||
event.startTime = record.start_time ? new Date(record.start_time).toISOString() : "" | ||
event.endTime = record.end_time ? new Date(record.end_time).toISOString() : "" | ||
event.location = record.location ?? "" | ||
event.fee = typeof record.fee === 'number' ? record.fee : 0 | ||
event.userID = record.user_id | ||
event.createdAt = record.created_at ? new Date(record.created_at).toISOString() : "" | ||
|
||
return event | ||
} | ||
|
||
} | ||
|
||
export default EventService |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
import ErrorHandler from "../../../utils/ErrorHandler"; | ||
import { supabase } from "../../../utils/supabase"; | ||
|
||
import User, { DBUser } from '../Entities/User'; | ||
import UserService from '../Services/UserService'; | ||
|
||
|
||
const USER_TABLE_NAME = "members" | ||
|
||
|
||
export default class UserController { | ||
|
||
/** | ||
* Get an array of users | ||
* | ||
* @usage userController.getUsers(<PARAMS>).then( | ||
* (users: Array<Users>) => { ... } | ||
* ) | ||
* | ||
* @param {string} fields - The columns to retrieve (comma-separated) | ||
* @param {string} orderBy - Which field to order by (leave blank if not needed) | ||
* @param {boolean} orderDescending - Whether to order in descending order (defaults to false) | ||
* @param {number} rangeStart - Starting index of fetch (defaults to 0) | ||
* @param {number} rangeEnd - Ending index of fetch (defaults to 100) | ||
* | ||
* @returns {Array<User>} - Array of users | ||
* | ||
* @see [https://supabase.com/docs/reference/javascript/order] | ||
* @see [https://supabase.com/docs/reference/javascript/range] | ||
* | ||
* @author Henry C. (@yeahlowflicker) | ||
*/ | ||
public async getUsers( | ||
fields: string, | ||
orderBy?: string, | ||
orderDescending?: boolean, | ||
rangeStart?: number, | ||
rangeEnd?: number | ||
) : Promise<Array<User> | null> { | ||
|
||
const query = supabase | ||
.from(USER_TABLE_NAME) | ||
.select(fields) | ||
.returns<Array<DBUser>>() | ||
|
||
if (orderBy) | ||
query.order(orderBy, { ascending: !orderDescending }) | ||
|
||
if (rangeStart !== undefined && rangeEnd !== undefined) | ||
query.range(rangeStart, rangeEnd) | ||
|
||
const { data, error } = await query | ||
|
||
// Error handling | ||
if (error) { | ||
ErrorHandler.handleSupabaseError(error) | ||
return null | ||
} | ||
|
||
// Initialize result array | ||
const users : Array<User> = [] | ||
|
||
// For each found DBUser, convert to User and append to result array | ||
data.forEach((record: DBUser) => { | ||
users.push( | ||
UserService.parseUser(record) | ||
) | ||
}) | ||
|
||
return users | ||
} | ||
|
||
|
||
|
||
/** | ||
* Find a single user by ID | ||
* | ||
* @usage userController.FindUserByID(<PARAMS>).then( | ||
* (user: User) => { ... } | ||
* ) | ||
* | ||
* @param {string} userID - Target user ID | ||
* @param {string} fields - The columns to retrieve | ||
* | ||
* @returns {User} - The target user entity (null if not found) | ||
* | ||
* @author Henry C. (@yeahlowflicker) | ||
*/ | ||
public async findUserByID(userID: string, fields?: string) : Promise<User | null> { | ||
|
||
const { data, error } = await supabase | ||
.from(USER_TABLE_NAME) | ||
.select(fields) | ||
.eq("uuid", userID) | ||
.returns<DBUser>() | ||
.limit(1) | ||
.single() | ||
|
||
|
||
// Error handling | ||
if (error) { | ||
ErrorHandler.handleSupabaseError(error) | ||
return null | ||
} | ||
|
||
if (!data) | ||
return null | ||
|
||
// Type conversion: DBUser -> User | ||
const user : User = UserService.parseUser(data) | ||
|
||
return user | ||
} | ||
|
||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
import { Database } from "../../../utils/database.types"; | ||
|
||
/** | ||
* This is a dummy-type inherited from the generated Supabase type | ||
*/ | ||
export type DBUser = Database['public']['Tables']['members']['Row']; | ||
|
||
|
||
/** | ||
* The User entity model | ||
* | ||
* @author Henry C. (@yeahlowflicker) | ||
*/ | ||
export default class User { | ||
public id: string = "" | ||
public username: string = "" | ||
public email: string = "" | ||
public phone: string = "" | ||
public avatar: string = "" | ||
public profileBackground: string = "" | ||
public joinedAt: Date = new Date() | ||
public identity: number = 0 | ||
public department: string = "" | ||
public grade: string = "" | ||
public bio: string = "" | ||
|
||
|
||
public convertIdentity(): string { | ||
switch (this.identity) { | ||
case 1: return "管理員" | ||
case 2: return "學生" | ||
case 3: return "校友" | ||
case 4: return "教職員" | ||
default: return "用戶" | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
import User, { DBUser } from "../Entities/User"; | ||
|
||
const UserService = { | ||
|
||
/** | ||
* Convert a user from default Supabase type to User entity | ||
* | ||
* @param {DBUser} record - The record retrieved from Supabase | ||
* @returns {User} - Converted user entity | ||
* | ||
* @author Henry C. (@yeahlowflicker) | ||
*/ | ||
parseUser(record: DBUser) : User { | ||
if (!record || typeof record !== 'object') | ||
throw new Error('Invalid record provided') | ||
|
||
if (!record.uuid) | ||
throw new Error('uuid is a required field'); | ||
|
||
const user = new User() | ||
|
||
user.id = record.uuid | ||
user.username = record.name | ||
user.email = record.fk_email | ||
user.identity = record.fk_identity | ||
user.avatar = record.avatar | ||
|
||
return user | ||
} | ||
|
||
} | ||
|
||
export default UserService |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
import { PostgrestError } from "@supabase/supabase-js"; | ||
|
||
/** | ||
* A universal error handler class. | ||
* | ||
* This will be called by all controllers and is useful for general | ||
* error-handling logic. | ||
* | ||
* @author Henry C. (@yeahlowflicker) | ||
*/ | ||
export default class ErrorHandler { | ||
|
||
public static handleSupabaseError(error: PostgrestError) { | ||
console.error(error) | ||
} | ||
|
||
} |