Skip to content

Commit

Permalink
[refactor] simplify Questionnaire & Team logic
Browse files Browse the repository at this point in the history
  • Loading branch information
TechQuery committed Aug 31, 2024
1 parent 240454e commit 57e0aa3
Show file tree
Hide file tree
Showing 12 changed files with 78 additions and 160 deletions.
6 changes: 3 additions & 3 deletions components/Activity/EnrollmentList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ const { t } = i18n;

export interface EnrollmentListLayoutProps
extends XScrollListProps<Enrollment> {
onPopUp?: (extensions: Enrollment['extensions']) => any;
onPopUp?: (extensions: Enrollment['form']) => any;
onVerify?: (userId: number, status: Enrollment['status']) => any;
}

Expand Down Expand Up @@ -46,15 +46,15 @@ export const EnrollmentListLayout: FC<EnrollmentListLayoutProps> = ({
name,
},
status,
extensions,
form,
createdAt,
},
index,
) => (
<tr key={id}>
<td>{index + 1}</td>
<td>
<Button variant="link" onClick={() => onPopUp?.(extensions)}>
<Button variant="link" onClick={() => onPopUp?.(form)}>
{name || email || mobilePhone}
</Button>
</td>
Expand Down
4 changes: 2 additions & 2 deletions components/Activity/EnrollmentStatistic.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ export default class EnrollmentStatisticCharts extends PureComponent<EnrollmentS
const {
// city = {},
status = {},
extensions = {},
answers = {},
} = this.props.store.statistic;

return (
Expand Down Expand Up @@ -93,7 +93,7 @@ export default class EnrollmentStatisticCharts extends PureComponent<EnrollmentS
<h2 className="my-4">{t('custom_questionnaire')}</h2>

<Row sm={1} md={2}>
{Object.entries(extensions).map(
{Object.entries(answers).map(
([title, answers]) =>
!isEmpty(answers) && (
<Col as="section" key={title}>
Expand Down
2 changes: 1 addition & 1 deletion components/Activity/QuestionnaireCreate.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { Question } from '@kaiyuanshe/openhackathon-service';
import { observer } from 'mobx-react';
import { BadgeInput } from 'mobx-restful-table';
import { FC, FormEvent } from 'react';
import { Button, Col, Form, Row } from 'react-bootstrap';
import { formToJSON } from 'web-utility';

import { Question } from '../../models/Activity/Question';
import { i18n } from '../../models/Base/Translation';

const { t } = i18n;
Expand Down
14 changes: 7 additions & 7 deletions models/Activity/Enrollment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export type EnrollmentFilter = Filter<Enrollment>;
export interface EnrollmentStatistic
extends Statistic<Enrollment>,
Statistic<Required<User>> {
extensions?: Record<string, Record<string, number>>;
answers?: Record<string, Record<string, number>>;
}

export class EnrollmentModel extends TableModel<Enrollment, EnrollmentFilter> {
Expand Down Expand Up @@ -73,13 +73,13 @@ export class EnrollmentModel extends TableModel<Enrollment, EnrollmentFilter> {
const { allItems } = this;

const questionGroup = groupBy(
allItems.map(({ extensions }) => extensions).flat(),
({ name }) => name,
allItems.map(({ form }) => form).flat(),
({ title }) => title,
);
const extensions = Object.fromEntries(
const answers = Object.fromEntries(
Object.entries(questionGroup).map(([title, answers]) => {
const { _, ...data } = countBy(answers, ({ value }) =>
/https?:\/\//.test(value) ? '_' : value.split(','),
const { _, ...data } = countBy(answers, ({ content }) =>
/https?:\/\//.test(content) ? '_' : content.split(','),
);
return [title, data];
}),
Expand All @@ -96,7 +96,7 @@ export class EnrollmentModel extends TableModel<Enrollment, EnrollmentFilter> {
...this.statistic,
createdAt,
// city,
extensions,
answers,
});
}
}
43 changes: 9 additions & 34 deletions models/Activity/Team.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,12 @@ import {
} from '@kaiyuanshe/openhackathon-service';
import { action, computed, observable } from 'mobx';
import { ListModel, Stream, toggle } from 'mobx-restful';
import { buildURLData } from 'web-utility';

import {
createListStream,
Filter,
InputData,
integrateError,
TableModel,
} from '../Base';
import { createListStream, Filter, InputData, TableModel } from '../Base';
import { WorkspaceModel } from '../Git';
import sessionStore from '../User/Session';
import { AwardAssignment } from './Award';
import { NameAvailability } from './index';

export type TeamFilter = Filter<Team> & BaseFilter;

Expand Down Expand Up @@ -97,35 +91,16 @@ export class TeamModel extends TableModel<Team, TeamFilter> {
@toggle('uploading')
async updateOne(data: InputData<Team>, id?: string) {
if (!id) {
try {
var { body: checkNameAvailabilityBody } =
await this.client.post<NameAvailability>(
`${this.baseURI}/checkNameAvailability`,
{ name: data.displayName },
);
} catch (error: any) {
throw integrateError(error);
}
const { nameAvailable, reason, message } = checkNameAvailabilityBody!;

if (!nameAvailable) {
const text = message.replace('{0}', data.displayName || '');

throw new ReferenceError(`${reason}\n${text}`);
}
const { body } = await this.client.get<Team[]>(
`${this.baseURI}?${buildURLData({ displayName: data.displayName })}`,
);
if (body![0]) throw new ReferenceError(`${data.displayName} is used`);
}
const team = await super.updateOne(data, id);

try {
const { body } = await (id
? this.client.patch<Team>(`${this.baseURI}/${id}`, data)
: this.client.put<Team>(this.baseURI, data));

await this.getSessionOne();
await this.getSessionOne();

return (this.currentOne = body!);
} catch (error: any) {
throw integrateError(error);
}
return team;
}
}

Expand Down
66 changes: 13 additions & 53 deletions models/Activity/index.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import {
Enrollment,
Extension,
Hackathon,
HackathonStatus,
Question,
Questionnaire,
} from '@kaiyuanshe/openhackathon-service';
import { action, observable } from 'mobx';
Expand All @@ -17,7 +17,6 @@ import { EnrollmentModel } from './Enrollment';
import { LogModel } from './Log';
import { AnnouncementModel } from './Message';
import { OrganizerModel } from './Organization';
import { Question } from './Question';
import { StaffModel } from './Staff';
import { TeamModel } from './Team';

Expand All @@ -28,23 +27,12 @@ export type ActivityListType =
| 'fresh'
| 'created';

export interface NameAvailability {
name: string;
nameAvailable: boolean;
reason: string;
message: string;
}

export interface ActivityFilter extends Filter<Hackathon> {
userId?: number;
listType?: ActivityListType;
orderby?: 'createdAt' | 'updatedAt' | 'hot';
}

export interface ActivityLogsFilter extends Filter<Hackathon> {
name: string;
}

export class ActivityModel extends TableModel<Hackathon, ActivityFilter> {
baseURI = 'hackathon';
indexKey = 'name' as const;
Expand Down Expand Up @@ -154,59 +142,31 @@ export class ActivityModel extends TableModel<Hackathon, ActivityFilter> {
const { body } = await this.client.get<Questionnaire>(
`${this.baseURI}/${activity}/questionnaire`,
);
const questionnaire = body!.extensions.map(
v =>
({
...JSON.parse(v.value),
id: v.name,
}) as Question,
);

return (this.questionnaire = questionnaire);
return (this.questionnaire = body!.questions);
}

@toggle('uploading')
createQuestionnaire(
extensions: Extension[],
activity = this.currentOne.name,
) {
updateQuestionnaire(questions: Question[], activity = this.currentOne.name) {
return this.client.put(`${this.baseURI}/${activity}/questionnaire`, {
extensions,
});
}

@toggle('uploading')
updateQuestionnaire(
extensions: Extension[],
activity = this.currentOne.name,
) {
return this.client.patch(`${this.baseURI}/${activity}/questionnaire`, {
extensions,
questions,
});
}

@toggle('uploading')
async deleteQuestionnaire(name: string) {
await this.client.delete(`${this.baseURI}/${name}/questionnaire`);

return (this.questionnaire = []);
}

@toggle('uploading')
async publishOne(name: string) {
const isPlatformAdmin = await platformAdmin.checkAuthorization();
const isPlatformAdmin = await platformAdmin.checkAuthorization(),
status = (
isPlatformAdmin ? 'online' : 'pendingApproval'
) as HackathonStatus;

await this.client.post(
`hackathon/${name}/${isPlatformAdmin ? 'publish' : 'requestPublish'}`,
);
this.changeOne({ status: 'online' as HackathonStatus.Online }, name, true);
await this.client.patch(`hackathon/${name}`, { status });

this.changeOne({ status }, name, true);
}

@toggle('uploading')
async signOne(name: string, extensions: Enrollment['extensions'] = []) {
await this.client.put(`${this.baseURI}/${name}/enrollment`, {
extensions,
});
async signOne(name: string, form: Enrollment['form'] = []) {
await this.client.put(`${this.baseURI}/${name}/enrollment`, { form });

return this.currentEnrollment?.getSessionOne();
}
Expand Down
8 changes: 0 additions & 8 deletions models/Base/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,14 +56,6 @@ export async function* createListStream<T>(
}
}

export const integrateError = ({ response }: HTTPError<ErrorData>) => {
const { title, errors, detail } = response.body || {};
const message = errors?.name?.join('');
return new ReferenceError(
message ? `${title || ''}\n${message}` : detail || '',
);
};

export abstract class TableModel<
D extends Base,
F extends InputData<D> = InputData<D>,
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,12 @@
"@babel/plugin-proposal-decorators": "^7.24.7",
"@babel/preset-react": "^7.24.7",
"@babel/preset-typescript": "^7.24.7",
"@kaiyuanshe/openhackathon-service": "^0.20.0",
"@kaiyuanshe/openhackathon-service": "^0.21.0",
"@octokit/openapi-types": "^22.2.0",
"@types/jsonwebtoken": "^9.0.6",
"@types/leaflet": "^1.9.12",
"@types/node": "^20.16.2",
"@types/react": "^18.3.4",
"@types/react": "^18.3.5",
"eslint": "^8.57.0",
"eslint-config-next": "^14.2.7",
"eslint-plugin-simple-import-sort": "^12.1.1",
Expand Down
20 changes: 10 additions & 10 deletions pages/activity/[name]/manage/participant/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Extension } from '@kaiyuanshe/openhackathon-service';
import { Answer } from '@kaiyuanshe/openhackathon-service';
import { observable } from 'mobx';
import { observer } from 'mobx-react';
import {
Expand Down Expand Up @@ -46,11 +46,11 @@ class ParticipantEditor extends PureComponent<ParticipantPageProps> {
store = activityStore.enrollmentOf(this.props.route.params!.name);

@observable
accessor extensions: Extension[] | undefined;
accessor answers: Answer[] | undefined;

render() {
const { resolvedUrl, params } = this.props.route,
{ extensions } = this;
{ answers } = this;

return (
<>
Expand All @@ -62,20 +62,20 @@ class ParticipantEditor extends PureComponent<ParticipantPageProps> {

<EnrollmentList
activity={params!.name}
onPopUp={extensions => (this.extensions = extensions)}
onPopUp={answers => (this.answers = answers)}
/>
<Modal show={!!extensions} onHide={() => (this.extensions = undefined)}>
<Modal show={!!answers} onHide={() => (this.answers = undefined)}>
<Modal.Header closeButton>
<Modal.Title>{t('questionnaire')}</Modal.Title>
</Modal.Header>
<Modal.Body as="ul">
{extensions?.map(({ name, value }) => (
<li key={name}>
<strong>{name}</strong>
<div>{value}</div>
{answers?.map(({ title, content }) => (
<li key={title}>
<strong>{title}</strong>
<div>{content}</div>
</li>
))}
{extensions?.[0] && t('no_news_yet')}
{answers?.[0] && t('no_news_yet')}
</Modal.Body>
</Modal>
</>
Expand Down
Loading

1 comment on commit 57e0aa3

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Deploy preview for open-hackathon ready!

✅ Preview
https://open-hackathon-8p8ssxb2l-techquerys-projects.vercel.app

Built with commit 57e0aa3.
This pull request is being automatically deployed with vercel-action

Please sign in to comment.