1
1
import { useMemo , useState } from "react" ;
2
- import { Button , ButtonGroup , Card } from "@netlify/sdk/ui/react/components" ;
2
+ import {
3
+ Button ,
4
+ ButtonGroup ,
5
+ Card ,
6
+ Tooltip ,
7
+ } from "@netlify/sdk/ui/react/components" ;
3
8
4
9
const NETLIFY_EPOCH = new Date ( "2014-11-09" ) ;
5
10
const SECONDS_SINCE_NETLIFY_EPOCH =
@@ -10,38 +15,47 @@ const CONFIG = {
10
15
{
11
16
threshold : Math . floor ( SECONDS_SINCE_NETLIFY_EPOCH / 60 / 60 / 24 / 365 ) , // ~10
12
17
multiplier : 2 ,
18
+ unit : "years" ,
13
19
} ,
14
20
{
15
21
threshold : Math . floor ( SECONDS_SINCE_NETLIFY_EPOCH / 60 / 60 / 24 / 30 ) , // ~100
16
22
multiplier : 2 ,
23
+ unit : "months" ,
17
24
} ,
18
25
{
19
26
threshold : Math . floor ( SECONDS_SINCE_NETLIFY_EPOCH / 60 / 60 / 24 / 7 ) , // ~500
20
27
multiplier : 4 ,
28
+ unit : "weeks" ,
21
29
} ,
22
30
{
23
31
threshold : Math . floor ( SECONDS_SINCE_NETLIFY_EPOCH / 60 / 60 / 24 ) , // ~4K
24
32
multiplier : 4 ,
33
+ unit : "days" ,
25
34
} ,
26
35
{
27
36
threshold : Math . floor ( SECONDS_SINCE_NETLIFY_EPOCH / 60 / 60 ) , // ~100K
28
37
multiplier : 8 ,
38
+ unit : "hours" ,
29
39
} ,
30
40
{
31
41
threshold : Math . floor ( SECONDS_SINCE_NETLIFY_EPOCH / 60 ) , // ~5M
32
42
multiplier : 16 ,
43
+ unit : "minutes" ,
33
44
} ,
34
45
{
35
46
threshold : Math . floor ( SECONDS_SINCE_NETLIFY_EPOCH ) , // ~300M
36
47
multiplier : 32 ,
48
+ unit : "seconds" ,
37
49
} ,
38
50
{
39
51
threshold : Math . floor ( SECONDS_SINCE_NETLIFY_EPOCH ) * 1000 , // ~300B
40
52
multiplier : 1024 ,
53
+ unit : "milliseconds" ,
41
54
} ,
42
55
{
43
56
threshold : Number . MAX_SAFE_INTEGER ,
44
57
multiplier : 1 ,
58
+ unit : "" ,
45
59
} ,
46
60
] ,
47
61
} ;
@@ -57,34 +71,74 @@ const ClickerButtonGroup = ({
57
71
( ) =>
58
72
completedLevels
59
73
. reduce (
60
- ( acc , { multiplier } ) => [
74
+ ( acc , level ) => [
61
75
...acc ,
62
- ( acc [ acc . length - 1 ] ?? 1 ) * multiplier ,
76
+ {
77
+ ...level ,
78
+ multiplier :
79
+ ( acc [ acc . length - 1 ] ?. multiplier ?? 1 ) * level . multiplier ,
80
+ } ,
63
81
] ,
64
- [ ] as number [ ] ,
82
+ [ ] as typeof CONFIG . levels ,
65
83
)
66
84
. reverse ( ) ,
67
85
[ completedLevels ] ,
68
86
) ;
69
87
70
88
return (
71
89
< ButtonGroup >
72
- { multipliers . map ( ( multiplier , index ) => (
73
- < Button key = { index } onClick = { ( ) => onClick ( multiplier ) } >
74
- Click { multiplier } x
75
- </ Button >
90
+ { multipliers . map ( ( level , index ) => (
91
+ < Tooltip
92
+ type = "info"
93
+ disabled = { level . multiplier === 1 }
94
+ contents = { `Netlify is ${ level . threshold } ${ level . unit } old!` }
95
+ >
96
+ < Button key = { index } onClick = { ( ) => onClick ( level . multiplier ) } >
97
+ Click { level . multiplier } x
98
+ </ Button >
99
+ </ Tooltip >
76
100
) ) }
77
101
</ ButtonGroup >
78
102
) ;
79
103
} ;
80
104
105
+ // TODO(serhalp) Check dark mode
106
+ // const NetlifyLogo = () => (
107
+ // <svg className="tw-size-9" viewBox="0 0 128 128">
108
+ // <path
109
+ // fill="rgb(12, 42, 42)"
110
+ // d="m125.2 54.8-52-52L71.3.9 69.2 0H58.8l-2.1.9-1.9 1.9-52 52-1.9 1.9-.9 2.1v10.3l.9 2.1 1.9 1.9 52 52 1.9 1.9 2.1.9h10.3l2.1-.9 1.9-1.9 52-52 1.9-1.9.9-2.1V58.8l-.9-2.1-1.8-1.9z"
111
+ // />
112
+ // <path
113
+ // fill="white"
114
+ // d="M78.9 80.5H71l-.7-.7V61.3c0-3.3-1.3-5.9-5.3-6-2-.1-4.4 0-6.9.1l-.4.4v24l-.7.7h-7.9l-.7-.7V48.1l.7-.7H67c6.9 0 12.6 5.6 12.6 12.6v19.8l-.7.7z"
115
+ // />
116
+ // <path
117
+ // fill="rgb(50, 230, 226)"
118
+ // d="m38.4 30.8 7.3 7.3v5.8l-.8.8h-5.8l-7.3-7.3v-1.1l5.5-5.5h1.1zm.2 37.2v-8l-.7-.7h-28l-.7.7v8l.7.7H38l.6-.7zm.5 15.7L31.8 91v1.1l5.5 5.5h1.1l7.3-7.3v-5.8l-.8-.8h-5.8zM60 11.3l-.6.7v25l.7.7H68l.7-.7V12l-.7-.7h-8zm0 79.1-.7.7v25l.7.7h8l.7-.7v-25l-.7-.7h-8zm58.1-31h-28l-.7.6v8l.7.7h28.1l.7-.7v-8l-.8-.6z"
119
+ // />
120
+ // </svg>
121
+ // );
122
+
123
+ const YouWin = ( ) => (
124
+ < div className = "tw-flex tw-flex-col tw-place-content-center" >
125
+ < div className = "tw-text-2xl tw-text-netlify-teal" > You win!</ div > { " " }
126
+ { /* FIXME(serhalp) Tailwind animations aren't working for some reason */ }
127
+ { /* <div className="tw-animate-spin"> */ }
128
+ { /* <NetlifyLogo /> */ }
129
+ { /* </div> */ }
130
+ </ div >
131
+ ) ;
132
+
81
133
export const Game = ( ) => {
82
134
const [ clickCount , setClickCount ] = useState ( 0 ) ;
83
135
const [ remainingLevels , setRemainingLevels ] = useState ( [ ...CONFIG . levels ] ) ;
84
136
const [ completedLevels , setCompletedLevels ] = useState ( [
85
- { threshold : 0 , multiplier : 1 } ,
137
+ { threshold : 0 , multiplier : 1 , unit : "" } ,
86
138
] ) ;
87
139
140
+ const hasWon = remainingLevels . length == 0 ;
141
+
88
142
const handleClick = ( count : number ) => {
89
143
setClickCount ( ( prev ) => {
90
144
const cur = prev + count ;
@@ -103,7 +157,9 @@ export const Game = () => {
103
157
return (
104
158
< >
105
159
< Card className = "tw-text-center tw-text-xl" >
106
- Clicks: < span className = "tw-font-bold" > { clickCount } </ span >
160
+ Clicks:{ " " }
161
+ < span className = "tw-font-bold" > { ! hasWon ? clickCount : "∞" } </ span >
162
+ { hasWon ? < YouWin /> : null }
107
163
</ Card >
108
164
< Card >
109
165
< ClickerButtonGroup
0 commit comments