Skip to content
This repository was archived by the owner on Oct 5, 2025. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
node_modules/
.next/
stories/
**/*.stories.*
56 changes: 56 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
module.exports = {
root: true,
parser: '@typescript-eslint/parser',
plugins: [
'@typescript-eslint',
],
extends: [
'next/core-web-vitals',
'airbnb',
'airbnb-typescript',
'airbnb/hooks',
'plugin:@typescript-eslint/recommended',
'plugin:@typescript-eslint/recommended-requiring-type-checking',
],
parserOptions: {
project: './tsconfig.json',
},
rules: {
// Clarifications are provided for each suppression

/**
* Forcing the use of default export affects readability and
* comprehensibility, especially in locally created package/module code -
* exporting at the discretion of the author is generally much
* more readable and appropriate in many cases
*/
'import/prefer-default-export': 'off',
/**
* Forcing <a> to have an href attribute directly conflicts with
* NextJS's next/link Link element best practices. In this project, Use
* next/link's Link with valid attributes with a bare <a> child element.
*/
'jsx-a11y/anchor-is-valid': 'off',
/**
* The default, for some reason, is to have a space between the closing
* bracket and the slash. This creates code that looks like `<br/ >`.
* IMHO, this is repulsive, so I am confidently declaring the use of
* whitespace before the self-closing slash instead - `<br />`
*/
'react/jsx-tag-spacing': [1, {
closingSlash: 'never', // <Element>< /Element> or <Element/ >
afterOpening: 'never', // < Element></ Element> or < Element/>
beforeClosing: 'never', // <Element ></Element >
beforeSelfClosing: 'always', // <Element />
}],
/**
* Function components are superior, that is all.
*/
'react/function-component-definition': [2, { namedComponents: 'arrow-function' }],
/**
* It's really up to the project maintainers to say what is and is not
* 'restricted' in a language, tbh. Just do good code reviews is what I say.
*/
'no-restricted-syntax': 'off',
},
};
4 changes: 4 additions & 0 deletions .husky/pre-commit
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"

yarn tsc --noEmit && yarn eslint --fix .
11 changes: 0 additions & 11 deletions .storybook/main.js

This file was deleted.

16 changes: 0 additions & 16 deletions .storybook/preview.js

This file was deleted.

4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ open-source [Next.js](https://nextjs.org/) project developed and maintained by
the volunteer-run CIMUN Department of Technology.

Chicago International Model United Nations (CIMUN) is an annual inter-scholastic
(high school) Model UN conference in Chicago, IL. Our focus is to create realistic
(high school) Model UN conference in Chicago, IL. Our focus is to create realistic
educational opportunities for young leaders in the scholastic MUN community.
We are organized by the Model United Nations Development Organization (MUNDO).

Expand All @@ -26,7 +26,7 @@ our continuous deployment needs.

<p align="center">
<a href="https://vercel.com?utm_source=model-un&utm_campaign=oss" target="blank">
<img src="./public/vercel-banner.svg" width="200" alt="Vercel Banner" />
<img src="public/vercel-banner.svg" width="200" alt="Vercel Banner" />
</a>
</p>

Expand Down
48 changes: 48 additions & 0 deletions app/api/AxiosHandler.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/**
* A simple implementation of an Axios-based request handler.
*/
import axios, { AxiosRequestConfig, AxiosResponse, Method } from 'axios';

export interface IAxiosHandler {
callRaw<T, D>(url: string, method: Method, data?: D, token?: string,
axiosConfig?: AxiosRequestConfig): Promise<AxiosResponse<T>>;

get<T>(url: string, axiosConfig?: AxiosRequestConfig): Promise<T>;

post<T, D>(url: string, data?: D, axiosConfig?: AxiosRequestConfig): Promise<T>;
}

export default class AxiosHandler implements IAxiosHandler {
callRaw = <T, D>(
url: string,
method: Method,
data?: D,
token?: string,
axiosConfig?: AxiosRequestConfig)
: Promise<AxiosResponse<T>> => {
// Create required request params
const params: AxiosRequestConfig = {
method,
url,
};
// Handle assigning auth header
if (token) {
params.headers = { Authorization: `Bearer ${token}` };
}
if (data) {
params.data = data;
}
// Perform request and return promise
return axios.request<T>({ ...params, ...axiosConfig });
};

get = async <T>(url: string, axiosConfig?: AxiosRequestConfig): Promise<T> => {
const res = await this.callRaw<T, null>(url, 'GET', null, null, axiosConfig);
return res.data;
};

post = async <T>(url: string, data?: unknown, axiosConfig?: AxiosRequestConfig): Promise<T> => {
const res = await this.callRaw<T, typeof data>(url, 'POST', data, null, axiosConfig);
return res.data;
};
}
41 changes: 41 additions & 0 deletions app/api/MundoClient.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/**
* Client to use for MUNDO API requests.
*/
import AxiosHandler, { IAxiosHandler } from '_api/AxiosHandler';
import FetchFormResponseDto from '_api/dto/FetchFormResponse.dto';
import SubmitFormDto from '_api/dto/SubmitForm.dto';
import Globs from '_constants/globs';
import SubmitFormResponseDto from '_api/dto/SubmitFormResponse.dto';

export interface IMundoClient extends IAxiosHandler {
PREFIX: string;

getFormTemplate(confId: string, formId: string): Promise<FetchFormResponseDto>;

postFormSubmission(confId: string, formId: string,
submitFormDto: SubmitFormDto): Promise<SubmitFormResponseDto>
}

export default class MundoClient extends AxiosHandler implements IMundoClient {
PREFIX = Globs.API.URL_PREFIX;

/*
* Retrieves data for a form to be rendered
*/
getFormTemplate = async (confId: string, formId: string): Promise<FetchFormResponseDto> => {
const url = `${this.PREFIX}/conferences/${confId}/forms/${formId}`;
return this.get<FetchFormResponseDto>(url);
};

/**
* POSTs a submission for a form
*/
postFormSubmission = async (
confId: string,
formId: string,
submitFormDto: SubmitFormDto,
): Promise<SubmitFormResponseDto> => {
const url = `${this.PREFIX}/conferences/${confId}/forms/${formId}/submissions`;
return this.post<SubmitFormResponseDto>(url, submitFormDto);
};
}
13 changes: 13 additions & 0 deletions app/api/dto/Base.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
export default class BaseDto {
id: number;

active: boolean;

createdBy: number;

updatedBy: number;

createdOn: Date;

updatedOn: Date;
}
5 changes: 5 additions & 0 deletions app/api/dto/FetchFormResponse.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import FormSectionDto from '_api/dto/FormSection.dto';

export default class FetchFormResponseDto {
sections: Array<FormSectionDto>;
}
20 changes: 20 additions & 0 deletions app/api/dto/FormField.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import BaseDto from '_api/dto/Base.dto';
import FormFieldValueDto from '_api/dto/FormFieldValue.dto';

export default class FormFieldDto extends BaseDto {
fieldType: string;

required: boolean;

// the index for the field in the form itself
index: number;

// the "question"
content: string;

// optional description
description?: string;

// optional values to select
values: FormFieldValueDto[];
}
7 changes: 7 additions & 0 deletions app/api/dto/FormFieldResponse.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
class FormFieldResponseDto {
id: number;

response: unknown;
}

export default FormFieldResponseDto;
7 changes: 7 additions & 0 deletions app/api/dto/FormFieldValue.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export default class FormFieldValueDto {
id: number;

fieldId: number;

value: string;
}
16 changes: 16 additions & 0 deletions app/api/dto/FormSection.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import BaseDto from '_api/dto/Base.dto';
import FormFieldDto from '_api/dto/FormField.dto';

export default class FormSectionDto extends BaseDto {
formId: number;

title: string;

subtitle?: string;

intro?: string;

outro?: string;

fields: Array<FormFieldDto>;
}
5 changes: 5 additions & 0 deletions app/api/dto/SubmitForm.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import FormFieldResponseDto from '_api/dto/FormFieldResponse.dto';

export default class SubmitFormDto {
responses: Array<FormFieldResponseDto>;
}
9 changes: 9 additions & 0 deletions app/api/dto/SubmitFormResponse.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import BaseDto from '_api/dto/Base.dto';

export default class SubmitFormResponseDto extends BaseDto {
formId: number;

// TODO: The schema for this is known, but is not necessary on submission.
// As a result, please reevaluate this decision as development continues.
responses: Array<unknown>;
}
13 changes: 13 additions & 0 deletions app/components/footer/Footer.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import React from "react";
// import { Story, Meta } from "@storybook/react";
import Footer from "./index";

export default {
title: "Layout/Footer",
component: Footer,
}
// } as Meta;

// const Template: Story = (args) => <Footer {...args} />;

// export const base = Template.bind({});
Loading