Skip to content

Commit ab6d52e

Browse files
CopilotTechQuery
andcommitted
Add MemberModel, ProductModel, and CommentBox component
- Added Member and Product types with corresponding models in Hackathon.ts - Updated team detail page to query members and products using new models - Added CommentBox component placeholder at bottom of team page - Improved product display with links to preview and source code Co-authored-by: TechQuery <19969570+TechQuery@users.noreply.github.com>
1 parent f792593 commit ab6d52e

3 files changed

Lines changed: 116 additions & 10 deletions

File tree

components/Activity/CommentBox.tsx

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import { FC } from 'react';
2+
import { Card } from 'react-bootstrap';
3+
4+
export const CommentBox: FC = () => {
5+
return (
6+
<Card className="mt-4">
7+
<Card.Body>
8+
<h3 className="h5">Comments</h3>
9+
<p className="text-muted">Comment functionality coming soon...</p>
10+
</Card.Body>
11+
</Card>
12+
);
13+
};

models/Hackathon.ts

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,3 +140,41 @@ export class ProjectModel extends BiDataTable<Project>() {
140140
};
141141
}
142142
}
143+
144+
export type Member = LarkBase &
145+
Record<'summary' | 'person' | 'skills' | 'githubAccount' | 'project' | 'status', TableCellValue>;
146+
147+
export class MemberModel extends BiDataTable<Member>() {
148+
client = larkClient;
149+
150+
queryOptions: BiDataQueryOptions = { text_field_as_array: false };
151+
152+
extractFields({ fields: { githubAccount, ...fields }, ...meta }: TableRecord<Member>) {
153+
return {
154+
...meta,
155+
...fields,
156+
githubAccount: normalizeText(githubAccount as TableCellText),
157+
};
158+
}
159+
}
160+
161+
export type Product = LarkBase &
162+
Record<
163+
'name' | 'project' | 'template' | 'link' | 'sourceLink' | 'file' | 'summary',
164+
TableCellValue
165+
>;
166+
167+
export class ProductModel extends BiDataTable<Product>() {
168+
client = larkClient;
169+
170+
queryOptions: BiDataQueryOptions = { text_field_as_array: false };
171+
172+
extractFields({ fields: { link, sourceLink, ...fields }, ...meta }: TableRecord<Product>) {
173+
return {
174+
...meta,
175+
...fields,
176+
link: normalizeText(link as TableCellText),
177+
sourceLink: normalizeText(sourceLink as TableCellText),
178+
};
179+
}
180+
}

pages/hackathon/[id]/team/[tid].tsx

Lines changed: 65 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,20 @@ import { cache, compose, errorLogger } from 'next-ssr-middleware';
44
import { FC, useContext } from 'react';
55
import { Badge, Card, Col, Container, Row, Tab, Tabs } from 'react-bootstrap';
66

7+
import { CommentBox } from '../../../../components/Activity/CommentBox';
78
import { LarkImage } from '../../../../components/LarkImage';
89
import { PageHead } from '../../../../components/Layout/PageHead';
910
import { Activity, ActivityModel } from '../../../../models/Activity';
10-
import { Person, PersonModel, Project, ProjectModel } from '../../../../models/Hackathon';
11+
import {
12+
Member,
13+
MemberModel,
14+
Person,
15+
PersonModel,
16+
Product,
17+
ProductModel,
18+
Project,
19+
ProjectModel,
20+
} from '../../../../models/Hackathon';
1121
import { I18nContext } from '../../../../models/Translation';
1222

1323
export const getServerSideProps = compose<{ id: string; tid: string }>(
@@ -23,20 +33,34 @@ export const getServerSideProps = compose<{ id: string; tid: string }>(
2333
const projectModel = new ProjectModel(appId, tableIdMap.Project);
2434
const team = await projectModel.getOne(params!.tid);
2535

36+
// Get approved members for this project
37+
const members = await new MemberModel(appId, tableIdMap.Member).getAll({
38+
project: team.name as string,
39+
status: 'approved',
40+
});
41+
42+
// Get person details for members
2643
const personModel = new PersonModel(appId, tableIdMap.Person);
2744
const allPeople = await personModel.getAll();
2845

29-
// Filter team members from all people based on the team's members field
30-
const teamMemberNames = (team.members as string[]) || [];
46+
// Filter team members from all people based on member records
47+
const memberPersonNames = members.map((m) => m.person as string);
3148
const teamMembers = allPeople.filter((person) =>
32-
teamMemberNames.includes(person.name as string),
49+
memberPersonNames.includes(person.name as string),
3350
);
3451

52+
// Get products for this project
53+
const products = await new ProductModel(appId, tableIdMap.Product).getAll({
54+
project: team.name as string,
55+
});
56+
3557
return {
3658
props: {
3759
activity,
3860
team,
3961
teamMembers,
62+
members,
63+
products,
4064
},
4165
};
4266
},
@@ -46,9 +70,11 @@ interface TeamPageProps {
4670
activity: Activity;
4771
team: Project;
4872
teamMembers: Person[];
73+
members: Member[];
74+
products: Product[];
4975
}
5076

51-
const TeamPage: FC<TeamPageProps> = observer(({ activity, team, teamMembers }) => {
77+
const TeamPage: FC<TeamPageProps> = observer(({ activity, team, teamMembers, products }) => {
5278
const { t } = useContext(I18nContext);
5379

5480
const { name: activityName } = activity;
@@ -134,12 +160,39 @@ const TeamPage: FC<TeamPageProps> = observer(({ activity, team, teamMembers }) =
134160
</Tab>
135161
<Tab eventKey="teamWork" title={t('team_works')} className="pt-2">
136162
<div className="mt-3">
137-
{team.products && (team.products as string[]).length > 0 ? (
163+
{products && products.length > 0 ? (
138164
<ul className="list-unstyled">
139-
{(team.products as string[]).map((product, index) => (
140-
<li key={index} className="mb-2">
141-
<Card body>
142-
<h5>{product}</h5>
165+
{products.map((product) => (
166+
<li key={product.id as string} className="mb-3">
167+
<Card>
168+
<Card.Body>
169+
<h5>{product.name as string}</h5>
170+
{product.summary && (
171+
<p className="text-muted">{product.summary as string}</p>
172+
)}
173+
<div className="d-flex gap-2 mt-2">
174+
{product.link && (
175+
<a
176+
href={product.link as string}
177+
target="_blank"
178+
rel="noreferrer"
179+
className="btn btn-sm btn-outline-primary"
180+
>
181+
{t('preview')}
182+
</a>
183+
)}
184+
{product.sourceLink && (
185+
<a
186+
href={product.sourceLink as string}
187+
target="_blank"
188+
rel="noreferrer"
189+
className="btn btn-sm btn-outline-secondary"
190+
>
191+
{t('source_code')}
192+
</a>
193+
)}
194+
</div>
195+
</Card.Body>
143196
</Card>
144197
</li>
145198
))}
@@ -175,6 +228,8 @@ const TeamPage: FC<TeamPageProps> = observer(({ activity, team, teamMembers }) =
175228
</Col>
176229
</Row>
177230
)}
231+
232+
<CommentBox />
178233
</Container>
179234
);
180235
});

0 commit comments

Comments
 (0)