# Table of Contents
- [Http Types](#http-types)
  - [Http Error](#http-error)
  - [HttpStatus](#httpstatus)
  - [HttpClient](#httpclient)
- [Utility Type](#utility-type)
  - [Model](#model)
  - [Auditable](#auditable)
  - [Role](#role)
  - [Login](#login)
    - [LoginInput](#logininput)
    - [LoginError](#loginerror)
  - [LogoutError](#logouterror)
  - [CurrentUserError](#currentusererror)
- [Note Types](#note-types)
  - [Note](#note)
  - [NoteError](#noteerror)
- [User Types](#user-types)
  - [User](#user)
  - [SeniorityInfo](#seniorityinfo)
  - [UserInput](#userinput)
  - [User Info](#user-info)
  - [UserError](#usererror)
- [Position Types](#position-types)
  - [Position](#position)
  - [PositionDetails](#positiondetails)
  - [Position Info](#position-info)
  - [PositionError](#positionerror)
- [Skill Types](#skill-types)
  - [Skill](#skill)
  - [SkillDetails](#skilldetails)
  - [Skill Info](#skill-info)
  - [SkillError](#skillerror)
- [Shift Types](#shift-types)
  - [Shift](#shift)
  - [ShiftDetails](#shiftdetails)
  - [Shift Info](#shift-info)
  - [ShiftError](#shifterror)
- [Schedule Types](#schedule-types)
  - [ScheduleInput](#scheduleinput)
  - [Schedule Info](#schedule-info)
  - [ScheduleError](#scheduleerror)
- [Time Slot Types](#time-slot-types)
  - [TimeSlot](#timeslot)
  - [TimeSlotInput](#timeslotinput)
  - [TimeSlotEdit](#timeslotedit)
  - [TimeSlotsEdited](#timeslotsedited)
  - [TimeSlot Info](#timeslot-info)
  - [TimeSlotError](#timesloterror)

# Http Types

## Http Error
```typescript
enum HttpErrorKind {
    UnexpectedStatus,
    Server,
    Client,
}

interface UnexpectedStatusError {
    kind: HttpErrorKind.UnexpectedStatus;
    status: HttpStatus,
}

interface ServerError {
    kind: HttpErrorKind.Server;
    status: HttpStatus,
}

interface ClientError {
    kind: HttpErrorKind.Client;
    message: string,
}

type HttpError = UnexpectedStatusError | ServerError | ClientError;
```

## HttpStatus
```typescript
enum HttpStatus {
    Ok = 200,
    Created = 201,
    NoContent = 204,
    Unauthorized = 401,
    NotFound = 404,
    Conflict = 409,
    ImATeaPot = 418,
    UnprocessableEntity = 422,
    NotImplemented = 501,
}
```

## HttpClient
```typescript
const HttpClient = {
    async post<Req, ServerRes, Res>(route: string, expectedStatus: HttpStatus, handle: (data: ServerRes) => Res, data?: Req): Promise<Result<Res, HttpError>>,

    async put<Req, ServerRes, Res>(route: string, expectedStatus: HttpStatus, handle: (data: ServerRes) => Res, data?: Req): Promise<Result<Res, HttpError>>,

    async get<ServerRes, Res>(route: string, expectedStatus: HttpStatus, handle: (data: ServerRes) => Res): Promise<Result<Res, HttpError>>,

    async patch<Req, ServerRes, Res>(route: string, expectedStatus: HttpStatus, handle: (data: ServerRes) => Res, data?: Req): Promise<Result<Res, HttpError>>,

    async delete<ServerRes, Res>(route: string, expectedStatus: HttpStatus, handle: (data: ServerRes) => Res): Promise<Result<Res, HttpError>>,
};
```

# Utility Types

## Model
```typescript
interface Model {
    id: number;
    created_at: DateTime;
    updated_at: DateTime;
}
```

## Auditable
```typescript
interface Auditable {
    created_by_id?: number;
    updated_by_id?: number;
    created_by?: UserMini;
    updated_by?: UserMini;
}
```

## Role
```typescript
enum Role {
    Root = 0,
    Admin,
    Manager,
    Officer,
    ReadOnly,
}
```

## Login

### LoginInput
```typescript
interface LoginInput {
    email: string;
    password: string;
}
```

### LoginError
```typescript
enum LoginErrorKind {
    AlreadyLoggedIn,
    BadCredentials,
    Http,
}

interface AlreadyLoggedInError {
    kind: LoginErrorKind.AlreadyLoggedIn;
}

interface BadCredentialsError {
    kind: LoginErrorKind.BadCredentials;
}

interface LoginHttpError {
    kind: LoginErrorKind.Http;
    error: HttpError;
}

type LoginError = AlreadyLoggedInError | BadCredentialsError | LoginHttpError;
```

## LogoutError
```typescript
enum LogoutErrorKind {
    NotLoggedIn,
    Http,
}

interface NotLoggedInError {
    kind: LogoutErrorKind.NotLoggedIn;
}

interface LogoutHttpError {
    kind: LogoutErrorKind.Http;
    error: HttpError;
}

type LogoutError = NotLoggedInError | LogoutHttpError;
```

## CurrentUserError
```typescript
enum CurrentUserErrorKind {
    NotLoggedIn,
    Http,
}

interface NotLoggedInError {
    kind: CurrentUserErrorKind.NotLoggedIn;
}

interface CurrentUserHttpError {
    kind: CurrentUserErrorKind.Http;
    error: HttpError;
}

type CurrentUserError = NotLoggedInError | CurrentUserHttpError;
```

# Note Types

## Note
```typescript
interface Note extends Model {
    content: string;
    user_id: number;
    created_by: UserMini;
}
```

## NoteError
```typescript
enum NoteErrorKind {
    DoesNotExist,
    PermissionDenied,
    Http,
}

interface NoteDoesNotExistError {
    kind: NoteErrorKind.DoesNotExist;
}

interface PermissionDeniedError {
    kind: NoteErrorKind.PermissionDenied;
}

interface NoteHttpError {
    kind: NoteErrorKind.Http;
    error: HttpError;
}

type NoteError = NoteDoesNotExistError | PermissionDeniedError | NoteHttpError;
```

# User Types

## User
```typescript
const user = {
    async getAll(): Promise<Result<User[], UserError>>,
    async modifySeniority(info: SeniorityInfo): Promise<Result<SeniorityInfo, UserError>>,
    async create(newUser: UserInput): Promise<Result<User, UserError>>,
    async get(userId: number): Promise<Result<User, UserError>>,
    async modify(user: User): Promise<Result<User, UserError>>,
    async remove(user: User): Promise<Result<void, UserError>>,
    async getAllNotes(user: User): Promise<Result<Note[], NoteError>>,
    async addNote(user: User, note: string): Promise<Result<Note, NoteError>>,
};
```

## SeniorityInfo
```typescript
interface SeniorityInfo {
    user_id: number;
    position_id: number;
    seniority: number;
}
```

## UserInput
```typescript
interface UserInput {
    first_name: string,
    middle_initial?: string,
    last_name: string,
    email: string,
    role: Role,
    unit?: string,
    vehicle?: string,
    emergency_number?: string,
    start_date?: string,
    skills: number[]
}
```

## UserMini
```typescript
interface UserMini {
    id: number;
    first_name: string;
    middle_initial?: string;
    last_name: string;
    email: string;
    image_id?: string;
}
```

## User Info
```typescript
interface User extends Model, Auditable {
    first_name: string;
    middle_initial?: string;
    last_name: string;
    email: string;
    image_id?: string;
    role: Role;
    position_id?: number;
    unit?: string;
    vehicle?: string;
    emergency_number?: string;
    seniority?: number;
    start_date?: DateTime;
}
```

## UserError
```typescript
enum UserErrorKind {
    NotLoggedIn,
    IncorrectPermissions,
    Http,
}

interface NotLoggedInError {
    kind: UserErrorKind.NotLoggedIn;
}

interface IncorrectPermissionsError {
    kind: UserErrorKind.IncorrectPermissions;
}

interface UserHttpError {
    kind: UserErrorKind.Http;
    error: HttpError;
}

type UserError = NotLoggedInError | IncorrectPermissionsError | UserHttpError;
```

# Position Types

## Position
```typescript
const position = {
    async getAll(): Promise<Result<Position[], PositionError>>,
    async create(newPos: PositionDetails): Promise<Result<Position, PositionError>>,
    async modify(position: Position): Promise<Result<Position, PositionError>>,
    async remove(position: Position): Promise<Result<void, PositionError>>,
};
```

## PositionDetails
```typescript
interface PositionDetails {
    name: string;
    description: string;
}
```

## Position Info
```typescript
interface Position extends Model, Auditable, PositionDetails {}
```

## PositionError
```typescript
enum PositionErrorKind {
    NotLoggedIn,
    IncorrectPermissions,
    Http,
}

interface NotLoggedInError {
    kind: PositionErrorKind.NotLoggedIn;
}

interface IncorrectPermissionsError {
    kind: PositionErrorKind.IncorrectPermissions;
}

interface PositionHttpError {
    kind: PositionErrorKind.Http;
    error: HttpError;
}

type PositionError = NotLoggedInError | IncorrectPermissionsError | PositionHttpError;
```

# Skill Types

## Skill
```typescript
const skill = {
    async getAll(): Promise<Result<Skill[], SkillError>>,
    async create(newSkill: SkillDetails): Promise<Result<Skill, SkillError>>,
    async modify(skill: Skill): Promise<Result<Skill, SkillError>>,
    async remove(skill: Skill): Promise<Result<void, SkillError>>,
};
```

## SkillDetails
```typescript
interface SkillDetails {
    code: string;
    description: string;
}
```

## Skill Info
```typescript
interface Skill extends Model, Auditable, SkillDetails {}
```

## SkillError
```typescript
enum SkillErrorKind {
    NotLoggedIn,
    IncorrectPermissions,
    Http,
}

interface NotLoggedInError {
    kind: SkillErrorKind.NotLoggedIn;
}

interface IncorrectPermissionsError {
    kind: SkillErrorKind.IncorrectPermissions;
}

interface SkillHttpError {
    kind: SkillErrorKind.Http;
    error: HttpError;
}

type SkillError = NotLoggedInError | IncorrectPermissionsError | SkillHttpError;
```

# Shift Types

## Shift
```typescript
const shift = {
    async getAll(): Promise<Result<Shift[], ShiftError>>,
    async create(newShift: ShiftDetails): Promise<Result<Shift, ShiftError>>,
    async modify(shift: Shift): Promise<Result<Shift, ShiftError>>,
    async remove(shift: Shift): Promise<Result<void, ShiftError>>,
};
```

## ShiftDetails
```typescript
interface ShiftDetails {
    name: string;
    color: string;
    start_time: Time;
    end_time: Time;
}
```

## Shift Info
```typescript
interface Shift extends Model, Auditable, ShiftDetails {}
```

## ShiftError
```typescript
enum ShiftErrorKind {
    NotLoggedIn,
    IncorrectPermissions,
    Http,
}

interface NotLoggedInError {
    kind: ShiftErrorKind.NotLoggedIn;
}

interface IncorrectPermissionsError {
    kind: ShiftErrorKind.IncorrectPermissions;
}

interface ShiftHttpError {
    kind: ShiftErrorKind.Http;
    error: HttpError;
}

type ShiftError = NotLoggedInError | IncorrectPermissionsError | ShiftHttpError;
```

# Schedule Types

## Schedule
```typescript
const schedule = {
    async getAll(): Promise<Result<Schedule[], ScheduleError>>,
    async create(newSchedule: ScheduleInput): Promise<Result<Schedule, ScheduleError>>,
    async copy(sourceId: number, newSchedule: ScheduleInput): Promise<Result<Schedule, ScheduleError>>,
    async get(scheduleId: number): Promise<Result<Schedule, ScheduleError>>,
    async modify(schedule: Schedule): Promise<Result<Schedule, ScheduleError>>,
    async remove(schedule: Schedule): Promise<Result<void, ScheduleError>>,
    async getAllNotes(schedule: Schedule): Promise<Result<Note[], NoteError>>,
    async addNote(schedule: Schedule, note: string): Promise<Result<Note, NoteError>>,
};
```

## ScheduleInput
```typescript
interface ScheduleInput {
    title: string;
    start_date: DateTime;
    end_date: DateTime;
    selection_start: DateTime;
    selection_end: DateTime;
}
```

## Schedule Info
```typescript
interface Schedule extends Model, Auditable {
    title: string;
    start_date: DateTime;
    end_date: DateTime;
    selection_start: DateTime;
    selection_end: DateTime;
    disabled: boolean;
    approver_id?: number;
    approved_by?: UserMini;
    time_slots: TimeSlot[];
}

```

## ScheduleError
```typescript
enum ScheduleErrorKind {
    NotLoggedIn,
    IncorrectPermissions,
    Http,
}

interface NotLoggedInError {
    kind: ScheduleErrorKind.NotLoggedIn;
}

interface IncorrectPermissionsError {
    kind: ScheduleErrorKind.IncorrectPermissions;
}

interface ScheduleHttpError {
    kind: ScheduleErrorKind.Http;
    error: HttpError;
}

type ScheduleError = NotLoggedInError | IncorrectPermissionsError | ScheduleHttpError;
```

# Time Slot Types

## TimeSlot
```typescript
const timeslot = {
    async getAll(): Promise<Result<TimeSlot[], TimeSlotError>>,
    async create(newTimeSlot: TimeSlotInput): Promise<Result<TimeSlot, TimeSlotError>>,
    async get(timeslotId: number): Promise<Result<TimeSlot, TimeSlotError>>,
    async modify(timeslot: TimeSlot): Promise<Result<TimeSlot, TimeSlotError>>,
    async temporirilyEdit(timeslotEdit: TimeSlotEdit): Promise<Result<TimeSlotsEdited, TimeSlotError>>,
    async remove(timeslot: TimeSlot): Promise<Result<void, TimeSlotError>>,
    async getAllNotes(timeslot: TimeSlot): Promise<Result<Note[], NoteError>>,
    async addNote(timeslot: TimeSlot, note: string): Promise<Result<Note, NoteError>>,
};
```

## TimeSlotInput
```typescript
interface TimeSlotInput {
    position_id: number;
    title: string;
    start_date: Date;
    end_date: Date;
    start_time: Time;
    end_time: Time;
    days: number;
    overtime: boolean;
}
```

## TimeSlotEdit
```typescript
interface TimeSlotEdit {
    id: number;
    start_date?: Date;
    end_date?: Date;
    start_time?: Time;
    end_time?: Time;
    assigned_id?: number;
}
```

## TimeSlotsEdited
```typescript
interface TimeSlotsEdited {
    updated: TimeSlot;
    created: TimeSlot[];
}
```

## TimeSlot Info
```typescript
interface TimeSlot extends Model, Auditable {
    schedule_id: number;
    position_id: number;
    title: string;
    unit?: string;
    vehicle?: string;
    emergency_number?: string;
    assigned_id?: number;
    assigned_to?: UserMini;
    edit_of_id?: number;
    start_date: Date;
    end_date: Date;
    start_time: Time;
    end_time: Time;
    days: number;
    overtime: boolean;
}
```

## TimeSlotError
```typescript
enum TimeSlotErrorKind {
    NotLoggedIn,
    IncorrectPermissions,
    Http,
}

interface NotLoggedInError {
    kind: TimeSlotErrorKind.NotLoggedIn;
}

interface IncorrectPermissionsError {
    kind: TimeSlotErrorKind.IncorrectPermissions;
}

interface TimeSlotHttpError {
    kind: TimeSlotErrorKind.Http;
    error: HttpError;
}

type TimeSlotError = NotLoggedInError | IncorrectPermissionsError | TimeSlotHttpError;
```