Skip to content

Commit c4725a6

Browse files
TechQueryCopilot
andcommitted
[refactor] simplify Copilot codes
Co-authored-by: Copilot <copilot@github.com>
1 parent a064205 commit c4725a6

7 files changed

Lines changed: 183 additions & 160 deletions

File tree

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
@import './theme.less';
2+
3+
.wrap {
4+
display: grid;
5+
gap: 0.75rem;
6+
max-width: 520px;
7+
}
8+
9+
.label {
10+
margin: 0;
11+
color: @muted;
12+
font-size: 0.72rem;
13+
font-family: @heading;
14+
letter-spacing: 0.1em;
15+
text-transform: uppercase;
16+
}
17+
18+
.grid {
19+
display: grid;
20+
grid-template-columns: repeat(4, minmax(0, 1fr));
21+
gap: 0.8rem;
22+
23+
li {
24+
gap: 0.7rem;
25+
box-shadow:
26+
inset 0 0 0 1px rgba(255, 255, 255, 0.03),
27+
0 0 26px rgba(44, 232, 255, 0.08);
28+
border: 1px solid rgba(44, 232, 255, 0.26);
29+
border-radius: 18px;
30+
background: linear-gradient(180deg, rgba(44, 232, 255, 0.08), rgba(44, 232, 255, 0.03));
31+
min-height: 120px;
32+
33+
strong {
34+
color: #fff;
35+
font-size: clamp(2.3rem, 4vw, 3.8rem);
36+
line-height: 1;
37+
font-family: @heading;
38+
letter-spacing: 0.08em;
39+
}
40+
41+
span {
42+
color: rgba(255, 255, 255, 0.72);
43+
font-size: 0.82rem;
44+
font-family: @heading;
45+
letter-spacing: 0.2em;
46+
text-transform: uppercase;
47+
}
48+
}
49+
}
50+
51+
@media (max-width: 767px) {
52+
.grid {
53+
grid-template-columns: repeat(2, minmax(0, 1fr));
54+
55+
li {
56+
min-height: 96px;
57+
58+
strong {
59+
font-size: 2rem;
60+
}
61+
}
62+
}
63+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import { TableCellValue } from 'mobx-lark';
2+
import { observer } from 'mobx-react';
3+
import { FC, useContext, useState } from 'react';
4+
5+
import { Agenda } from '../../../models/Hackathon';
6+
import { I18nContext } from '../../../models/Translation';
7+
import { Countdown, TimeUnit } from './Countdown';
8+
import styles from './AgendaCountdown.module.less';
9+
import { agendaTypeLabelOf, resolveCountdownState } from './utility';
10+
11+
export interface AgendaCountdownProps {
12+
agendaItems: Agenda[];
13+
endTime?: TableCellValue;
14+
startTime?: TableCellValue;
15+
units: TimeUnit[];
16+
}
17+
18+
export const AgendaCountdown: FC<AgendaCountdownProps> = observer(
19+
({ agendaItems, endTime, startTime, units }) => {
20+
const { t } = useContext(I18nContext);
21+
const [referenceTime, setReferenceTime] = useState(Date.now());
22+
const { nextItem: nextAgendaItem, countdownTo } = resolveCountdownState(
23+
agendaItems,
24+
referenceTime,
25+
startTime,
26+
endTime,
27+
);
28+
29+
if (!countdownTo) return null;
30+
31+
const countdownLabel = nextAgendaItem
32+
? agendaTypeLabelOf(nextAgendaItem.type, t, t('agenda'))
33+
: t('event_duration');
34+
35+
return (
36+
<div className={styles.wrap}>
37+
{countdownLabel && <p className={styles.label}>{countdownLabel}</p>}
38+
39+
<Countdown
40+
className={styles.grid}
41+
endTime={countdownTo}
42+
onEnd={() => setReferenceTime(Date.now())}
43+
units={units}
44+
/>
45+
</div>
46+
);
47+
},
48+
);

components/Activity/Hackathon/Countdown.tsx

Lines changed: 38 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import { computed, observable } from 'mobx';
22
import { observer } from 'mobx-react';
33
import { ObservedComponent, reaction } from 'mobx-react-helper';
4+
import { HTMLAttributes } from 'react';
5+
import { Second, TimeData } from 'web-utility';
46

57
export interface TimeUnit {
68
scale: number;
@@ -12,107 +14,88 @@ interface TimeSection {
1214
label: string;
1315
}
1416

15-
export interface CountdownProps {
16-
className?: string;
17-
endTime?: string | Date | number;
18-
onEnd?: () => void;
17+
export interface CountdownProps extends HTMLAttributes<HTMLOListElement> {
1918
units: TimeUnit[];
19+
endTime: TimeData;
20+
onEnd?: (endTime: TimeData) => any;
2021
}
2122

2223
@observer
2324
export class Countdown extends ObservedComponent<CountdownProps> {
2425
@observable
2526
accessor rest = 0;
2627

27-
private timer?: number;
28+
private timer = 0;
2829

29-
private get target() {
30-
const { endTime } = this.observedProps;
31-
32-
if (!endTime) return NaN;
33-
34-
const ms =
35-
typeof endTime === 'number'
36-
? endTime
37-
: endTime instanceof Date
38-
? endTime.getTime()
39-
: new Date(endTime).getTime();
40-
41-
return Number.isFinite(ms) ? ms : NaN;
30+
get endTimestamp() {
31+
return +new Date(this.props.endTime || Date.now());
4232
}
4333

4434
@computed
4535
get timeSections(): TimeSection[] {
4636
const { units } = this.observedProps;
4737
let { rest } = this;
4838

49-
return units.reduce(
50-
(list, { label }, index) => {
51-
const scale = units
52-
.slice(index)
53-
.map(({ scale }) => scale)
54-
.reduce((sum, scale) => sum * scale, 1);
39+
return units.reduce((list, { label }, index) => {
40+
const scale = units
41+
.slice(index)
42+
.map(({ scale }) => scale)
43+
.reduce((sum, scale) => sum * scale, 1);
5544

56-
const value = ~~(rest / scale);
57-
rest -= value * scale;
45+
const value = ~~(rest / scale);
46+
rest -= value * scale;
5847

59-
list.push({ value, label });
60-
return list;
61-
},
62-
[] as TimeSection[],
63-
);
48+
list.push({ value, label });
49+
return list;
50+
}, [] as TimeSection[]);
6451
}
6552

6653
tick = () => {
67-
const rest = this.target - Date.now();
54+
const { onEnd, endTime } = this.props,
55+
rest = this.endTimestamp - Date.now();
6856

6957
if (rest > 0) {
7058
this.rest = rest;
7159
} else {
7260
this.rest = 0;
73-
74-
if (this.timer) {
75-
window.clearInterval(this.timer);
76-
this.timer = undefined;
77-
this.props.onEnd?.();
78-
}
61+
this.stop();
62+
onEnd?.(endTime);
7963
}
8064
};
8165

66+
stop() {
67+
if (this.timer) {
68+
window.clearInterval(this.timer);
69+
this.timer = 0;
70+
}
71+
}
72+
8273
componentDidMount() {
8374
super.componentDidMount();
8475
this.initTimer();
8576
}
8677

87-
@reaction((_this: Countdown) => _this.observedProps.endTime)
78+
@reaction(_this => _this.observedProps.endTime)
8879
initTimer() {
89-
if (this.timer) {
90-
window.clearInterval(this.timer);
91-
this.timer = undefined;
92-
}
93-
80+
this.stop();
9481
this.tick();
95-
this.timer = window.setInterval(this.tick, 1000);
82+
this.timer = window.setInterval(this.tick, Second);
9683
}
9784

9885
componentWillUnmount() {
9986
super.componentWillUnmount();
100-
101-
if (this.timer) window.clearInterval(this.timer);
87+
this.stop();
10288
}
10389

10490
render() {
105-
const { className } = this.props;
91+
const { className = '', ...props } = this.props;
10692
const { timeSections } = this;
10793

10894
return (
109-
<ol className={`list-unstyled${className ? ` ${className}` : ''} m-0`}>
110-
{timeSections.map(({ value, label }, index) => (
111-
<li
112-
key={`${index}-${label}`}
113-
className="d-flex flex-column justify-content-center align-items-center"
114-
>
115-
<strong>{String(value).padStart(2, '0')}</strong>
95+
<ol className={`list-unstyled m-0 ${className}`} {...props}>
96+
{timeSections.map(({ value, label }) => (
97+
<li key={label} className="d-flex flex-column justify-content-center align-items-center">
98+
<strong>{(value + '').padStart(2, '0')}</strong>
11699
<span>{label}</span>
117100
</li>
118101
))}

components/Activity/Hackathon/Hero.module.less

Lines changed: 6 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -179,54 +179,10 @@
179179
}
180180
}
181181

182-
.countdownWrap {
183-
display: grid;
184-
gap: 0.75rem;
185-
max-width: 520px;
186-
}
187-
188-
.countdownLabel {
189-
color: @muted;
190-
font-size: 0.72rem;
191-
font-family: @heading;
192-
letter-spacing: 0.1em;
193-
text-transform: uppercase;
194-
}
195-
196-
.countdownGrid {
197-
display: grid;
198-
grid-template-columns: repeat(4, minmax(0, 1fr));
199-
gap: 0.8rem;
200-
201-
li {
202-
gap: 0.7rem;
203-
box-shadow:
204-
inset 0 0 0 1px rgba(255, 255, 255, 0.03),
205-
0 0 26px rgba(44, 232, 255, 0.08);
206-
border: 1px solid rgba(44, 232, 255, 0.26);
207-
border-radius: 18px;
208-
background: linear-gradient(180deg, rgba(44, 232, 255, 0.08), rgba(44, 232, 255, 0.03));
209-
min-height: 120px;
210-
211-
strong {
212-
color: #fff;
213-
font-size: clamp(2.3rem, 4vw, 3.8rem);
214-
line-height: 1;
215-
font-family: @heading;
216-
letter-spacing: 0.08em;
217-
}
218-
219-
span {
220-
color: rgba(255, 255, 255, 0.72);
221-
font-size: 0.82rem;
222-
font-family: @heading;
223-
letter-spacing: 0.2em;
224-
text-transform: uppercase;
225-
}
226-
}
227-
}
228-
229182
.actionButton {
183+
// prettier-ignore
184+
.button-primary();
185+
230186
box-shadow: 0 0 28px rgba(44, 232, 255, 0.14);
231187
border-color: rgba(44, 232, 255, 0.48);
232188
background: rgba(44, 232, 255, 0.08);
@@ -240,6 +196,9 @@
240196
}
241197

242198
.actionButtonGhost {
199+
// prettier-ignore
200+
.button-ghost();
201+
243202
border-color: rgba(255, 255, 255, 0.16);
244203
background: rgba(255, 255, 255, 0.03);
245204
color: rgba(255, 255, 255, 0.82);
@@ -442,16 +401,4 @@
442401
.heroBadge {
443402
font-size: 0.72rem;
444403
}
445-
446-
.countdownGrid {
447-
grid-template-columns: repeat(2, minmax(0, 1fr));
448-
449-
li {
450-
min-height: 96px;
451-
452-
strong {
453-
font-size: 2rem;
454-
}
455-
}
456-
}
457404
}

0 commit comments

Comments
 (0)