Skip to content

Commit c5893d3

Browse files
committed
[migrate] replace SMS Code with Email OTP for sign-in
[fix] many detail bugs [optimize] update Upstream packages
1 parent 89b34b4 commit c5893d3

File tree

19 files changed

+932
-903
lines changed

19 files changed

+932
-903
lines changed

.env.development

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
NEXT_PUBLIC_API_HOST = http://localhost:8080

components/Project/EvaluationDisplay.tsx

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,25 +3,36 @@ import { Box, Typography } from '@mui/material';
33
import { observer } from 'mobx-react';
44
import { FC, useContext } from 'react';
55

6-
import { I18nContext } from '../../models/Translation';
6+
import { i18n, I18nContext } from '../../models/Translation';
77
import userStore from '../../models/User';
88

9+
export const DevelopmentScopeName = ({ t }: typeof i18n) => [
10+
t('product_prototype'),
11+
t('ui_design'),
12+
t('desktop'),
13+
t('mobile'),
14+
t('server'),
15+
];
16+
917
export const EvaluationDisplay: FC<RequirementEvaluation> = observer(
1018
({
1119
title,
1220
scopes = [],
21+
models,
1322
developerCount,
1423
designerCount,
1524
workload,
1625
monthPeriod,
1726
budget,
1827
factor,
1928
}) => {
20-
const { t } = useContext(I18nContext),
29+
const i18n = useContext(I18nContext);
30+
const { t } = i18n,
2131
{ roles } = userStore.session || {};
2232

2333
return (
2434
<Box
35+
className="prose"
2536
sx={{
2637
'& .evaluation-item': {
2738
marginBottom: 1,
@@ -55,7 +66,21 @@ export const EvaluationDisplay: FC<RequirementEvaluation> = observer(
5566
<Box component="ul" sx={{ mt: 0.5 }}>
5667
{scopes.map(scope => (
5768
<Box key={scope} component="li" sx={{ ml: 1 }}>
58-
{scope}
69+
{DevelopmentScopeName(i18n)[scope]}
70+
</Box>
71+
))}
72+
</Box>
73+
</Box>
74+
)}
75+
{models && models.length > 0 && (
76+
<Box className="evaluation-item">
77+
<Typography component="h4" sx={{ fontWeight: 600 }}>
78+
{t('feature_modules')}
79+
</Typography>
80+
<Box component="ol" sx={{ mt: 0.5 }}>
81+
{models.map((model, index) => (
82+
<Box key={index} component="li" sx={{ ml: 1 }}>
83+
{model}
5984
</Box>
6085
))}
6186
</Box>

components/Project/NewCard.tsx

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { FC, useContext } from 'react';
66

77
import { I18nContext } from '../../models/Translation';
88

9-
export const ProjectCard: FC<Project> = observer(({ id, name, projectStatus }) => {
9+
export const ProjectCard: FC<Project> = observer(({ id, name, status }) => {
1010
const { t } = useContext(I18nContext);
1111

1212
return (
@@ -21,23 +21,18 @@ export const ProjectCard: FC<Project> = observer(({ id, name, projectStatus }) =
2121
px: 1,
2222
py: 0.5,
2323
borderRadius: 1,
24-
bgcolor:
25-
projectStatus === '1'
26-
? 'success.light'
27-
: projectStatus === '0'
28-
? 'grey.200'
29-
: 'warning.light',
24+
bgcolor: status === 1 ? 'success.light' : status === 0 ? 'grey.200' : 'warning.light',
3025
color:
31-
projectStatus === '1'
26+
status === 1
3227
? 'success.contrastText'
33-
: projectStatus === '0'
28+
: status === 0
3429
? 'text.primary'
3530
: 'warning.contrastText',
3631
}}
3732
>
38-
{projectStatus === '1'
33+
{status === 1
3934
? t('project_open')
40-
: projectStatus === '0'
35+
: status === 0
4136
? t('project_closed')
4237
: t('project_pending')}
4338
</Typography>

components/Project/PrototypeGeneratorToolbar.tsx

Lines changed: 21 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,11 @@
1+
import { PrototypeVersion, PrototypeVersionStatus } from '@idea2app/data-server';
12
import { Box, Button, CircularProgress, Link, Typography } from '@mui/material';
23
import { observable } from 'mobx';
34
import { observer } from 'mobx-react';
45
import { ObservedComponent } from 'mobx-react-helper';
56
import { sleep } from 'web-utility';
67

7-
import {
8-
PrototypeVersion,
9-
PrototypeVersionModel,
10-
PrototypeVersionStatus,
11-
} from '../../models/PrototypeVersion';
8+
import { PrototypeVersionModel } from '../../models/PrototypeVersion';
129
import { i18n, I18nContext } from '../../models/Translation';
1310

1411
export interface PrototypeGeneratorToolbarProps {
@@ -26,7 +23,7 @@ export class PrototypeGeneratorToolbar extends ObservedComponent<
2623
versionStore = new PrototypeVersionModel(this.props.projectId);
2724

2825
@observable
29-
accessor version: PrototypeVersion | null = null;
26+
accessor version: PrototypeVersion | undefined;
3027

3128
@observable
3229
accessor isPolling = false;
@@ -40,7 +37,7 @@ export class PrototypeGeneratorToolbar extends ObservedComponent<
4037
void this.loadVersion();
4138
}
4239

43-
if (this.version?.status === PrototypeVersionStatus.GENERATING) {
40+
if (this.version?.status === 'processing') {
4441
this.startPolling();
4542
}
4643
}
@@ -67,10 +64,7 @@ export class PrototypeGeneratorToolbar extends ObservedComponent<
6764
const updatedVersion = await this.versionStore.getVersionByMessageId(this.props.messageId);
6865
this.version = updatedVersion;
6966

70-
if (
71-
updatedVersion?.status === PrototypeVersionStatus.COMPLETED ||
72-
updatedVersion?.status === PrototypeVersionStatus.FAILED
73-
) {
67+
if (updatedVersion?.status === 'completed' || updatedVersion?.status === 'failed') {
7468
this.isPolling = false;
7569
break;
7670
}
@@ -81,7 +75,9 @@ export class PrototypeGeneratorToolbar extends ObservedComponent<
8175

8276
handleGenerateClick = async () => {
8377
try {
84-
const newVersion = await this.versionStore.updateOne({ messageId: this.props.messageId });
78+
const newVersion = await this.versionStore.updateOne({
79+
evaluationMessage: this.props.messageId,
80+
});
8581
if (newVersion) {
8682
this.version = newVersion;
8783
}
@@ -125,9 +121,9 @@ export class PrototypeGeneratorToolbar extends ObservedComponent<
125121

126122
return (
127123
<Box sx={{ display: 'flex', gap: 1, flexWrap: 'wrap' }}>
128-
{version!.previewUrl && (
124+
{version!.previewLink && (
129125
<Link
130-
href={version!.previewUrl}
126+
href={version!.previewLink}
131127
target="_blank"
132128
rel="noopener noreferrer"
133129
sx={{
@@ -140,9 +136,9 @@ export class PrototypeGeneratorToolbar extends ObservedComponent<
140136
{t('view_preview')}
141137
</Link>
142138
)}
143-
{version!.logUrl && (
139+
{version!.gitLogsLink && (
144140
<Link
145-
href={version!.logUrl}
141+
href={version!.gitLogsLink}
146142
target="_blank"
147143
rel="noopener noreferrer"
148144
sx={{
@@ -168,9 +164,9 @@ export class PrototypeGeneratorToolbar extends ObservedComponent<
168164
<Typography variant="body2" color="error" sx={{ fontSize: '0.875rem' }}>
169165
{version!.errorMessage || t('prototype_generation_failed')}
170166
</Typography>
171-
{version!.logUrl && (
167+
{version!.gitLogsLink && (
172168
<Link
173-
href={version!.logUrl}
169+
href={version!.gitLogsLink}
174170
target="_blank"
175171
rel="noopener noreferrer"
176172
sx={{
@@ -190,18 +186,6 @@ export class PrototypeGeneratorToolbar extends ObservedComponent<
190186
render() {
191187
const { version } = this;
192188

193-
let content = null;
194-
195-
if (!version || version.status === PrototypeVersionStatus.PENDING) {
196-
content = this.renderPending();
197-
} else if (version.status === PrototypeVersionStatus.GENERATING) {
198-
content = this.renderGenerating();
199-
} else if (version.status === PrototypeVersionStatus.COMPLETED) {
200-
content = this.renderCompleted();
201-
} else if (version.status === PrototypeVersionStatus.FAILED) {
202-
content = this.renderFailed();
203-
}
204-
205189
return (
206190
<Box
207191
sx={{
@@ -211,7 +195,13 @@ export class PrototypeGeneratorToolbar extends ObservedComponent<
211195
borderColor: 'divider',
212196
}}
213197
>
214-
{content}
198+
{!version || version.status === 'pending'
199+
? this.renderPending()
200+
: version.status === 'processing'
201+
? this.renderGenerating()
202+
: version.status === 'completed'
203+
? this.renderCompleted()
204+
: this.renderFailed()}
215205
</Box>
216206
);
217207
}

components/ScrollBoundary.tsx

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,17 +11,25 @@ export type ScrollBoundaryProps = PropsWithChildren<
1111
}
1212
>;
1313

14-
function touch(edge: EdgePosition, onTouch: TouchHandler) {
15-
return (node: HTMLElement | null) => {
16-
if (node) {
17-
new IntersectionObserver(([{ isIntersecting }]) => {
18-
if (isIntersecting) {
19-
onTouch(edge);
20-
}
21-
}).observe(node);
22-
}
23-
};
24-
}
14+
const EdgeOrder: EdgePosition[] = ['top', 'right', 'bottom', 'left'];
15+
16+
const touch = (edge: EdgePosition, onTouch: TouchHandler) => (node: HTMLElement | null) => {
17+
if (!node) return;
18+
19+
const anchor = node.parentElement?.parentElement;
20+
21+
const { overflowX, overflowY } = anchor ? getComputedStyle(anchor) : {};
22+
23+
const root = `${overflowX}${overflowY}`.match(/auto|scroll/) ? anchor : null;
24+
25+
const edgeMargins = Array(4).fill('0px');
26+
edgeMargins[EdgeOrder.indexOf(edge)] = '200px';
27+
28+
new IntersectionObserver(([{ isIntersecting }]) => isIntersecting && onTouch(edge), {
29+
root,
30+
rootMargin: edgeMargins.join(' '),
31+
}).observe(node);
32+
};
2533

2634
export const ScrollBoundary: FC<ScrollBoundaryProps> = ({
2735
className = '',
@@ -30,7 +38,7 @@ export const ScrollBoundary: FC<ScrollBoundaryProps> = ({
3038
left,
3139
right,
3240
bottom,
33-
children
41+
children,
3442
}) => (
3543
<div className={className} style={{ position: 'relative' }}>
3644
<div

components/User/SessionBox.tsx

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { User } from '@idea2app/data-server';
2-
import { Drawer, List, ListItem, ListItemButton, ListItemText } from '@mui/material';
2+
import { Box, List, ListItem, ListItemButton, ListItemText, Modal } from '@mui/material';
33
import { observable } from 'mobx';
44
import { observer } from 'mobx-react';
55
import Link from 'next/link';
@@ -51,20 +51,20 @@ export class SessionBox extends Component<SessionBoxProps> {
5151
</List>
5252
</div>
5353
<main className="flex-1 pb-3">
54-
<PageHead title={title} />
55-
56-
<h1 className="mb-4 text-3xl font-bold">{title}</h1>
57-
5854
{children}
5955

60-
<Drawer
61-
anchor="right"
62-
slotProps={{ paper: { className: 'p-4', style: { width: '400px' } } }}
63-
open={this.modalShown}
64-
onClose={() => (this.modalShown = false)}
65-
>
66-
<SessionForm onSignIn={() => window.location.reload()} />
67-
</Drawer>
56+
<Modal open={this.modalShown}>
57+
<Box
58+
className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 rounded p-4 shadow-lg"
59+
sx={{
60+
width: '400px',
61+
maxWidth: '90vw',
62+
bgcolor: 'background.paper',
63+
}}
64+
>
65+
<SessionForm onSignIn={() => (this.modalShown = false)} />
66+
</Box>
67+
</Modal>
6868
</main>
6969
</div>
7070
);

0 commit comments

Comments
 (0)