Skip to content
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
40 changes: 27 additions & 13 deletions models/Award.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,25 @@
import { BiDataQueryOptions, BiDataTable, BiSearch, TableCellValue } from 'mobx-lark';
import { BiDataQueryOptions, BiDataTable, BiSearch, TableCellValue, TableRecord, normalizeTextArray } from 'mobx-lark';

import { larkClient } from './Base';
import { LarkBase, larkClient } from './Base';
import { AwardTableId, LarkBitableId } from './configuration';

export type Award = Record<
| 'awardName'
| `nominee${'Name' | 'Desc'}`
| 'videoUrl'
| 'reason'
| 'nominator'
| 'createdAt'
| 'votes',
TableCellValue
>;
export type AwardStatus = 'nominated' | 'reviewing' | 'voting' | 'awarded' | 'declined';

export type Award = LarkBase &
Record<
| 'awardName'
| `nominee${'Name' | 'Desc' | 'Email' | 'GitHub'}`
| 'videoUrl'
| 'reason'
| 'nominator'
| 'nominatorEmail'
| 'status'
| 'votes'
| 'tokenId'
| 'tokenTxHash'
| 'awardedAt',
TableCellValue
>;

export class AwardModel extends BiDataTable<Award>() {
client = larkClient;
Expand All @@ -25,5 +32,12 @@ export class AwardModel extends BiDataTable<Award>() {
}

export class SearchAwardModel extends BiSearch<Award>(AwardModel) {
searchKeys = ['awardName', 'nomineeName', 'nomineeDesc', 'reason', 'nominator'];
searchKeys = [
'awardName',
'nomineeName',
'nomineeDesc',
'nomineeGitHub',
'reason',
'nominator',
];
}
48 changes: 48 additions & 0 deletions pages/api/award/[id]/workflow.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import type { NextApiRequest, NextApiResponse } from 'next';
import { AwardModel } from '../../../../models/Award';

const VALID_TRANSITIONS: Record<string, string[]> = {
nominated: ['reviewing', 'declined'],
reviewing: ['voting', 'declined'],
voting: ['awarded'],
awarded: [],
declined: [],
};

export default async function handler(req: NextApiRequest, res: NextApiResponse) {
if (req.method !== 'POST') {
return res.status(405).json({ error: 'Method not allowed' });
}

const { id } = req.query;
const { status } = req.body;

if (!id || !status) {
return res.status(400).json({ error: 'Missing id or status' });
}

try {
const awardModel = new AwardModel();
const awards = await awardModel.getAll();
const award = awards.find((a) => a.id === id);

if (!award) {
return res.status(404).json({ error: 'Award not found' });
}

const currentStatus = (award.status ?? 'nominated') as string;
const allowed = VALID_TRANSITIONS[currentStatus];

if (!allowed || !allowed.includes(status)) {
return res.status(400).json({
error: `Invalid status transition: ${currentStatus} -> ${status}`,
allowedTransitions: allowed,
});
}

await awardModel.updateOne(id as string, { status });
return res.status(200).json({ success: true, from: currentStatus, to: status });
} catch (error) {
return res.status(500).json({ error: String(error) });
}
}
33 changes: 33 additions & 0 deletions pages/api/award/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import type { NextApiRequest, NextApiResponse } from 'next';
import { AwardModel } from '../../../models/Award';

export default async function handler(req: NextApiRequest, res: NextApiResponse) {
const awardModel = new AwardModel();

switch (req.method) {
case 'GET': {
const awards = await awardModel.getAll();
return res.status(200).json(awards);
}
case 'POST': {
const body = req.body;
try {
const result = await awardModel.createOne(body);
return res.status(201).json(result);
} catch (error) {
return res.status(400).json({ error: String(error) });
}
}
case 'PUT': {
const { id, ...data } = req.body;
try {
await awardModel.updateOne(id, data);
return res.status(200).json({ success: true });
} catch (error) {
return res.status(400).json({ error: String(error) });
}
}
default:
return res.status(405).json({ error: 'Method not allowed' });
}
}