Skip to content

Commit efa729e

Browse files
committed
feat: frontend for revised sample app
1 parent 023fbc5 commit efa729e

File tree

4 files changed

+260
-29
lines changed

4 files changed

+260
-29
lines changed

public/js/client.js

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
function anonymizeCoordinate(coord) {
2+
const addOrSubtract = Math.random() > 0.5 ? 1 : -1
3+
const randomVariation = Math.random() * 0.5 * addOrSubtract
4+
return (parseFloat(coord) + randomVariation).toFixed(2)
5+
}
6+
7+
function getLocalTimezone() {
8+
return new Intl.DateTimeFormat().resolvedOptions().timeZone
9+
}
10+
11+
async function getGeolocationFromIP() {
12+
const response = await fetch('/geolocate')
13+
return response.json()
14+
}
15+
16+
function updateLocationText(lat, lon) {
17+
const latString = `${Math.abs(lat)}° ${lat > 0 ? 'N' : 'S'}`;
18+
const lonString = `${Math.abs(lon)}° ${lon > 0 ? 'E' : 'W'}`;
19+
document.querySelector('#coords').innerHTML = `Location: ${latString}, ${lonString}`
20+
}
21+
22+
// function updateWeatherData
23+
24+
function geolocate() {
25+
26+
console.log(`Timezone: ${localTimezone}`)
27+
const coordsOutput = document.querySelector('#coords')
28+
29+
function success(position) {
30+
console.log('Device geolocation successful')
31+
const lat = anonymizeCoordinate(position.coords.latitude)
32+
const lon = anonymizeCoordinate(position.coords.longitude)
33+
updateLocationText(lat, lon)
34+
}
35+
36+
function deviceGeolocationUnavailable() {
37+
console.log('Device geolocation failed')
38+
getGeolocationFromIP().then((coords) => {
39+
updateLocationText(anonymizeCoordinate(coords.lat), anonymizeCoordinate(coords.lon))
40+
})
41+
}
42+
43+
if (navigator.geolocation) {
44+
coordsOutput.innerHTML = 'Retrieving your location...'
45+
navigator.geolocation.getCurrentPosition(success, deviceGeolocationUnavailable);
46+
} else {
47+
deviceGeolocationUnavailable()
48+
}
49+
}
50+
51+
const localTimezone = getLocalTimezone()
52+
document.querySelector('#geolocate').addEventListener('click', geolocate)

public/stylesheets/style.css

Lines changed: 152 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,179 @@
11
body {
2-
margin: 0 auto;
2+
margin: 0 auto;
33
height: 100%;
4-
background: #FFFFFF;
4+
background: #175DFD;
55
text-align: center;
6+
max-width: 1280px;
7+
padding: 1rem;
68
}
79
#logo{
8-
margin: 40px auto 0;
10+
margin: 20px auto;
11+
}
12+
13+
#header {
14+
border: solid 0px #175DFD;
15+
border-radius: 1rem;
16+
padding: 1rem 3rem 2rem;
17+
/* width: fit-content; */
18+
margin: 0 auto;
19+
min-width: 66%;
20+
box-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
21+
background: #FFFFFF;
22+
max-width: 960px;
23+
}
24+
25+
#header a{
26+
width: 240px;
27+
height: 44px;
28+
border-radius: 6px;
29+
padding: 8px 16px;
30+
background: #175DFD;
31+
box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.15);
32+
font-family: Avenir,sans-serif;
33+
color: #FFFFFF;
34+
text-decoration: none;
35+
}
36+
37+
#success {
38+
display: flex;
39+
flex-direction: row;
40+
flex-wrap: wrap;
41+
/* margin: 50px auto; */
42+
margin: 25px auto;
43+
width: 100%;
44+
justify-content: space-around;
945
}
46+
1047
#rocket{
11-
width: 550px;
12-
height: 340px;
13-
margin: 50px auto;
48+
width: 275px;
49+
height: 170px;
50+
/* margin: auto 5%; */
51+
flex: none;
1452
}
15-
#content h1{
53+
54+
#message{
55+
flex: none;
56+
/* margin: auto 5%; */
57+
}
58+
#message h1{
1659
font-family: Avenir,sans-serif;
1760
font-weight: 500;
1861
font-size: 80px;
1962
text-align: center;
2063
color: #175DFD;
2164
margin: 0px;
2265
}
23-
#content h2{
66+
#message h2{
2467
font-family: Avenir,sans-serif;
2568
font-weight: 500;
2669
font-size: 32px;
2770
text-align: center;
2871
color: #00911d;
2972
margin: 0px;
3073
}
31-
#content p{
74+
75+
#content {
76+
margin: 25px auto;
77+
padding: 25px;
78+
border: solid 0px #175DFD;
79+
border-radius: 1rem;
80+
box-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
81+
background: #FFFFFF;
82+
display: flex;
83+
flex-direction: row;
84+
flex-wrap: wrap;
85+
justify-content: space-around;
86+
text-align: left;
87+
}
88+
89+
#content h3 {
90+
text-align: left;
91+
}
92+
93+
#content :is(p, div) {
3294
font-family: Avenir,sans-serif;
3395
font-weight: 500;
3496
font-size: 16px;
35-
text-align: center;
36-
margin: 20px 0 50px;
97+
text-align: left;
98+
/* margin: 20px 0 50px; */
3799
color: #222222;
38100
}
39-
#content a{
40-
width: 240px;
41-
height: 44px;
42-
border-radius: 6px;
43-
padding: 8px 16px;
44-
background: #175DFD;
45-
box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.15);
46-
font-family: Avenir,sans-serif;
47-
color: #FFFFFF;
48-
text-decoration: none;
49-
}
101+
102+
#location {
103+
flex-basis: 33.333333%;
104+
}
105+
106+
#weather {
107+
flex-basis: 50%;
108+
}
109+
110+
#forecast {
111+
display: flex;
112+
flex-direction: column;
113+
flex-wrap: wrap;
114+
width: fit-content;
115+
margin: 0 auto;
116+
min-width: 300px;
117+
/* text-align: center; */
118+
/* align-items: center; */
119+
}
120+
121+
/* #forecast div {
122+
padding: 10px;
123+
} */
124+
125+
#forecast > div {
126+
justify-content: space-between;
127+
display: flex;
128+
flex-direction: row;
129+
}
130+
131+
#forecast > div > :is(.label, .value) {
132+
display: inline-block;
133+
/* margin: 0 auto; */
134+
}
135+
136+
#forecast > div > .label {
137+
align-self: left;
138+
font-weight: 600;
139+
}
140+
141+
#forecast > div > .value {
142+
align-self: right;
143+
}
144+
145+
/* #forecast .forecastLabel {
146+
font-weight: 600;
147+
margin-inline-end: 15px;
148+
align-self: left;
149+
} */
150+
151+
#currentTemperature {
152+
align-self: center;
153+
/* width: 100%; */
154+
margin: 0 auto;
155+
}
156+
157+
#currentTemperature span {
158+
font-size: 5rem;
159+
vertical-align: top;
160+
display: inline-block;
161+
align-self: right;
162+
}
163+
164+
#currentTemperature #currentTempUnit {
165+
font-size: 2rem;
166+
padding-top: 10px;
167+
vertical-align: top;
168+
}
169+
170+
#forecast #currentDescription {
171+
font-size: 2rem;
172+
margin: 0 auto;
173+
}
174+
175+
#forecast #currentWindCompass {
176+
text-decoration: underline;
177+
text-decoration-style: dotted;
178+
text-decoration-color: #175DFD;
179+
}

views/currentConditions.pug

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
h3 Weather Forecast
2+
button(id="geolocate") Get Local Forecast
3+
p(id="coords")
4+
#forecast
5+
if forecast.current
6+
if forecast.current.temperature_2m
7+
#currentTemperature
8+
span(id="currentTempVal") #{forecast.current.temperature_2m[0]}
9+
span(id="currentTempUnit") #{forecast.current.temperature_2m[1]}
10+
if forecast.current.description
11+
#currentDescription
12+
span #{forecast.current.description}
13+
if forecast.current.relative_humidity_2m
14+
#currentHumidity
15+
.label
16+
span(class="forecastLabel") Humidity
17+
.value
18+
span(id="currentHumidityVal") #{forecast.current.relative_humidity_2m[0]}
19+
span(id="currentHumidityUnit") #{forecast.current.relative_humidity_2m[1]}
20+
if forecast.current.feels_like
21+
#currentFeel
22+
.label
23+
span(class="forecastLabel") Feels Like
24+
.value
25+
span(id="currentFeelVal") #{forecast.current.feels_like[0]}
26+
span(id="currentFeelUnit") #{forecast.current.feels_like[1]}
27+
if forecast.current.wind_speed_10m
28+
#currentWind
29+
.label
30+
span(class="forecastLabel") Wind
31+
.value
32+
span(id="currentWindSpeed") #{forecast.current.wind_speed_10m[0]}#{forecast.current.wind_speed_10m[1]}
33+
|  @ 
34+
span(id="currentWindDirection") #{forecast.current.wind_direction_10m[0]}#{forecast.current.wind_direction_10m[1]}
35+
|  
36+
span(id="currentWindCompass", title=forecast.current.wind_compass) (#{forecast.current.wind_compass_short})
37+

views/index.pug

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,23 @@ html(lang="en")
88
link(rel="stylesheet", href="/stylesheets/style.css")
99
title CTO.ai
1010
body
11-
img(id="logo", src="/images/cto_logo_primary.svg", alt="CTO.ai logo")
12-
br
13-
img(id="rocket", src="/images/cto_rocket.png", alt="CTO.ai Rocket")
11+
#header
12+
img(id="logo", src="/images/cto_logo_primary.svg", alt="CTO.ai logo")
13+
#success
14+
img(id="rocket", src="/images/cto_rocket.png", alt="CTO.ai Rocket")
15+
#message
16+
h1 Success!
17+
h2 #{release_no}
18+
br
19+
a(href="https://cto.ai/docs") Explore our Documentation
20+
1421
#content
15-
h1 Success!
16-
h2 #{release_no}
17-
p Congratulations, your service was deployed successfully on the Developer Control Plane!
18-
a(href="https://cto.ai/docs") Explore our Documentation
22+
#location
23+
h3 Status Message
24+
p Congratulations, your service was deployed successfully on the Developer Control Plane!
25+
p You are visiting this site from <strong>#{locationName}</strong> via <code>#{ipAddr}</code>.
26+
#weather
27+
include currentConditions.pug
28+
29+
30+
script(defer, src="/js/client.js")

0 commit comments

Comments
 (0)