feat: startup splash for user configuration
This commit is contained in:
parent
4dd15d52bb
commit
56c315c301
|
@ -10,6 +10,13 @@
|
|||
</head>
|
||||
<body>
|
||||
|
||||
<div id="start-splash">
|
||||
<img class="center" src="oct.jpg"></img>
|
||||
<input class="center" type="text" id="username" placeholder="Choose a username!" onkeyup="usernameInputUpdated(event)"></input>
|
||||
<!--<ul class="center" id="interest-selection"></ul>-->
|
||||
<a id="advance-button" class="center" href="#" onclick="advanceSplash()">Choose some interests!</a>
|
||||
</div>
|
||||
|
||||
<!-- blocks are added by JavaScript so container starts empty -->
|
||||
<div id="block-container"></div>
|
||||
|
||||
|
|
207
main.js
207
main.js
|
@ -8,7 +8,34 @@ const adjectives = [
|
|||
"analytical", "motivated", "solution-focused", "committed", "agile"
|
||||
];
|
||||
|
||||
const interests = [
|
||||
"music", "comedy", "travel", "technology", "hiking", "nature", "food", "movies",
|
||||
"culture", "art", "activism", "community", "books", "baking", "creativity", "fitness",
|
||||
"fashion", "wellness", "history", "adventure", "gaming", "gardening", "sustainability",
|
||||
"coding", "coffee", "DIY", "crafts", "pets", "animals", "humor", "languages", "sports",
|
||||
"competition", "meditation", "mindfulness", "design", "concerts", "innovation", "museums",
|
||||
"future", "writing", "relaxation", "photography", "compassion", "nutrition", "style",
|
||||
"restaurants", "gadgets", "inspiration", "literature", "outdoors", "wildlife", "conservation",
|
||||
"motivation", "beauty", "culinary arts", "festivals", "exploration", "knowledge", "camping",
|
||||
"archeology", "triathlon", "endurance", "luxury", "wine", "fine dining", "audio equipment",
|
||||
"sound quality", "startups", "entrepreneurship", "extreme sports", "philosophy", "survival",
|
||||
"environment", "politics", "running", "gastronomy", "genres", "software", "current events",
|
||||
"recipes", "listening", "discovery", "expression", "reading", "recommendations", "news",
|
||||
"analysis", "trends", "dining", "reviews", "rescue", "welfare", "health", "artists", "cooking"
|
||||
];
|
||||
|
||||
var localUser = {
|
||||
user: null,
|
||||
interests: [],
|
||||
postingStyle: null
|
||||
};
|
||||
var splashStep = 0;
|
||||
const maxInterests = 3;
|
||||
|
||||
// configuration
|
||||
const localMode = false;
|
||||
const showSplash = false;
|
||||
|
||||
const blockContainer = document.getElementById("block-container");
|
||||
const postCountElem = document.getElementById("post-count");
|
||||
const postTotalElem = document.getElementById("post-total");
|
||||
|
@ -215,13 +242,18 @@ function makePostFromJson(json) {
|
|||
}
|
||||
|
||||
function getCurrentUser() {
|
||||
// return some default values if we didn't do the initial configuration
|
||||
if (!showSplash) {
|
||||
return {
|
||||
"user": "ktyl",
|
||||
"interests": ["trains", "trains", "trains"],
|
||||
"posting_style": "borderline maniacal train content"
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
"user": "theChief",
|
||||
"interests": [
|
||||
"gen-ai",
|
||||
"blockchain",
|
||||
"nfts"
|
||||
],
|
||||
"user": localUser.user,
|
||||
"interests": localUser.interests,
|
||||
"posting_style": "just the most truly inane takes"
|
||||
};
|
||||
}
|
||||
|
@ -243,12 +275,10 @@ function writePost(postCallback) {
|
|||
body: "local mode post (local mode post)"
|
||||
});
|
||||
postCallback(post);
|
||||
//blockContainer.insertBefore(post.getElement(), getTopPost());
|
||||
} else {
|
||||
fetch("https://api.wayfarer.games/singularity/generate-posts.php", request)
|
||||
.then(response => response.json())
|
||||
.then(makePostFromJson)
|
||||
//.then(post => blockContainer.insertBefore(post.getElement(), getTopPost()));
|
||||
.then(postCallback);
|
||||
}
|
||||
}
|
||||
|
@ -302,6 +332,162 @@ function init() {
|
|||
window.addEventListener("scroll", handleInfiniteScroll);
|
||||
}
|
||||
|
||||
|
||||
function chooseInterest(interest) {
|
||||
if (localUser.interests.length == maxInterests) {
|
||||
console.error(`can't choose more than ${maxInterests} interests`);
|
||||
return;
|
||||
}
|
||||
|
||||
localUser.interests.push(interest);
|
||||
|
||||
const interestsTextElem = document.getElementById("interests-text");
|
||||
|
||||
if (localUser.interests.length != maxInterests) {
|
||||
interestsTextElem.innerHTML = getInterestsTextValue(localUser.interests.length);
|
||||
return;
|
||||
}
|
||||
|
||||
const advanceButtonElem = document.getElementById("advance-button");
|
||||
advanceButtonElem.innerHTML = "Begin!";
|
||||
advanceButtonElem.style.visibility = "visible";
|
||||
|
||||
interestsTextElem.remove();
|
||||
const interestsListElem = document.getElementById("interest-selection");
|
||||
interestsListElem.remove();
|
||||
}
|
||||
|
||||
function getInterestsSubset() {
|
||||
const count = 20;
|
||||
let subset = [];
|
||||
|
||||
while (subset.length < count) {
|
||||
const interest = interests[Math.floor(Math.random() * interests.length)];
|
||||
|
||||
// skip if it's already included
|
||||
if (subset.includes(interest))
|
||||
continue;
|
||||
|
||||
// skip if the user has already chosen it
|
||||
if (localUser.interests.includes(interest))
|
||||
continue;
|
||||
|
||||
subset.push(interest);
|
||||
}
|
||||
|
||||
return subset;
|
||||
}
|
||||
|
||||
function populateSplashInterests() {
|
||||
|
||||
const rootElem = document.getElementById("interest-selection");
|
||||
if (rootElem == null)
|
||||
return;
|
||||
|
||||
// clear existing interests
|
||||
rootElem.innerHTML = "";
|
||||
|
||||
const interestsSubset = getInterestsSubset();
|
||||
|
||||
for (let i = 0; i < interestsSubset.length; i++) {
|
||||
const interest = interestsSubset[i];
|
||||
const listItemElem = document.createElement("li");
|
||||
rootElem.appendChild(listItemElem);
|
||||
|
||||
const buttonElem = document.createElement("a");
|
||||
buttonElem.innerHTML = `#${interest}`;
|
||||
buttonElem.addEventListener("click", () => {
|
||||
chooseInterest(interest);
|
||||
populateSplashInterests();
|
||||
});
|
||||
listItemElem.appendChild(buttonElem);
|
||||
}
|
||||
}
|
||||
|
||||
function getInterestsTextValue(numChosenInterests) {
|
||||
return `Choose some interests! (${numChosenInterests}/${maxInterests})`;
|
||||
}
|
||||
|
||||
function usernameInputUpdated(event) {
|
||||
const inputElem = document.getElementById("username");
|
||||
const buttonElem = document.getElementById("advance-button");
|
||||
const isNameEmpty = inputElem.value.length == "";
|
||||
buttonElem.style.visibility = isNameEmpty ? "hidden" : "visible";
|
||||
|
||||
if (isNameEmpty)
|
||||
return;
|
||||
|
||||
if (event.key == "Enter") {
|
||||
advanceSplash();
|
||||
}
|
||||
}
|
||||
|
||||
function chooseName() {
|
||||
// check that a name has been chosen
|
||||
const inputElem = document.getElementById("username");
|
||||
if (!inputElem.value) {
|
||||
console.error("a name needs to be entered!");
|
||||
return;
|
||||
}
|
||||
|
||||
splashStep = 1;
|
||||
localUser.user = inputElem.value;
|
||||
|
||||
// TODO: disable button until name has been chosen
|
||||
|
||||
// TODO: insert interest selection elements before name input
|
||||
//writePost(post => blockContainer.insertBefore(post.getElement(), getTopPost()));
|
||||
const splashElem = document.getElementById("start-splash");
|
||||
|
||||
const interestsTextElem = document.createElement("p");
|
||||
interestsTextElem.innerHTML = getInterestsTextValue(0);
|
||||
interestsTextElem.id = "interests-text";
|
||||
interestsTextElem.className = "center";
|
||||
splashElem.insertBefore(interestsTextElem, inputElem);
|
||||
|
||||
const interestsListElem = document.createElement("ul");
|
||||
interestsListElem.className = "center";
|
||||
interestsListElem.id = "interest-selection";
|
||||
splashElem.insertBefore(interestsListElem, inputElem);
|
||||
|
||||
populateSplashInterests();
|
||||
|
||||
// remove name input
|
||||
inputElem.remove();
|
||||
|
||||
const advanceButtonElem = document.getElementById("advance-button");
|
||||
advanceButtonElem.style.visibility = "hidden";
|
||||
|
||||
splashStep = 1;
|
||||
}
|
||||
|
||||
function chooseInterests() {
|
||||
if (localUser.interests.length < maxInterests) {
|
||||
console.error(`need to choose ${maxInterests} interests`);
|
||||
return;
|
||||
}
|
||||
|
||||
console.log("TODO: generate user posting style");
|
||||
}
|
||||
|
||||
function removeSplash() {
|
||||
document.getElementById("start-splash").remove();
|
||||
}
|
||||
|
||||
function advanceSplash() {
|
||||
switch(splashStep) {
|
||||
case 0:
|
||||
chooseName();
|
||||
break;
|
||||
case 1:
|
||||
chooseInterests();
|
||||
removeSplash();
|
||||
break;
|
||||
default:
|
||||
console.error(`nothing defined for splash step ${splashStep}`);
|
||||
}
|
||||
}
|
||||
|
||||
function loadDataFromEndpoint(endpoint, callback) {
|
||||
fetch(endpoint)
|
||||
.then(response => response.json())
|
||||
|
@ -311,6 +497,7 @@ function loadDataFromEndpoint(endpoint, callback) {
|
|||
});
|
||||
}
|
||||
|
||||
|
||||
const usersUrl = localMode ? "users.json" : "https://api.wayfarer.games/singularity/users.json";
|
||||
const postsUrl = localMode ? "posts.json" : "https://api.wayfarer.games/singularity/posts.json";
|
||||
loadDataFromEndpoint(usersUrl, json => { users = json.users; });
|
||||
|
@ -333,3 +520,7 @@ loadDataFromEndpoint(postsUrl, json => {
|
|||
|
||||
postTotalElem.innerHTML = Object.keys(posts).length;
|
||||
});
|
||||
|
||||
if (!showSplash) {
|
||||
removeSplash();
|
||||
}
|
||||
|
|
96
styles.css
96
styles.css
|
@ -1,15 +1,17 @@
|
|||
:root {
|
||||
--header-height: 64px;
|
||||
--background-color: #374955;
|
||||
--accent-color: #86b1cc;
|
||||
--blue-gray: #374955;
|
||||
--sky-blue: #86b1cc;
|
||||
--comment-column-width: 3px;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-family: "Poppins", sans-serif;
|
||||
font-weight: 400;
|
||||
font-style: normal;
|
||||
background-color: var(--background-color);
|
||||
background-color: var(--sky-blue);
|
||||
}
|
||||
|
||||
@media only screen and (min-width: 800px) {
|
||||
|
@ -23,6 +25,77 @@ body {
|
|||
}
|
||||
}
|
||||
|
||||
#start-splash {
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
background-color: white;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.center {
|
||||
display: block;
|
||||
margin: auto;
|
||||
padding: auto;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#start-splash img {
|
||||
max-width: 40vw;
|
||||
margin-top: 10vh;
|
||||
}
|
||||
|
||||
#start-splash input {
|
||||
margin: 2em auto;
|
||||
border: none;
|
||||
background-color: var(--sky-blue);
|
||||
color: white;
|
||||
border-radius: 16px;
|
||||
font-size: 1.5em;
|
||||
padding: 4px 8px;
|
||||
}
|
||||
|
||||
#advance-button {
|
||||
width: 20%;
|
||||
margin: 2em auto;
|
||||
color: white;
|
||||
background-color: var(--sky-blue);
|
||||
text-align: center;
|
||||
visibility: hidden;
|
||||
padding: 4px 8px;
|
||||
border-radius: 16px;
|
||||
}
|
||||
|
||||
#interests-text {
|
||||
color: var(--blue-gray);
|
||||
}
|
||||
|
||||
#interest-selection {
|
||||
width: 80%;
|
||||
padding: 8px;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
#interest-selection li {
|
||||
display: inline;
|
||||
margin: .5em;
|
||||
}
|
||||
|
||||
#interest-selection li a {
|
||||
padding: 4px 8px;
|
||||
border-radius: 16px;
|
||||
color: white;
|
||||
background-color: var(--sky-blue);
|
||||
transition: all 200ms ease-in-out;
|
||||
}
|
||||
|
||||
#interest-selection li a:hover {
|
||||
background-color: var(--blue-gray);
|
||||
}
|
||||
|
||||
#block-container {
|
||||
display: flex;
|
||||
|
@ -51,19 +124,20 @@ body {
|
|||
border-radius: calc(var(--header-height) / 2);
|
||||
margin-top: calc(var(--header-height) / 8);
|
||||
padding: calc(var(--header-height) / 8) calc(var(--header-height) / 4);
|
||||
background-color: var(--accent-color);
|
||||
color: var(--backround-color);
|
||||
background-color: var(--sky-blue);
|
||||
color: white;
|
||||
cursor: pointer;
|
||||
transition: all 200ms ease-in-out;
|
||||
}
|
||||
|
||||
.reply-button:hover {
|
||||
background-color: var(--background-color);
|
||||
background-color: var(--blue-gray);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.reply-button:active {
|
||||
background-color: white;
|
||||
color: var(--blue-gray);
|
||||
}
|
||||
|
||||
.post-header {
|
||||
|
@ -82,16 +156,16 @@ body {
|
|||
|
||||
.write-post {
|
||||
cursor: pointer;
|
||||
color: var(--background-color);
|
||||
color: var(--blue-gray);
|
||||
}
|
||||
|
||||
.write-post:hover {
|
||||
background-color: var(--accent-color);
|
||||
background-color: var(--sky-blue);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.write-post:active {
|
||||
background-color: var(---background-color);
|
||||
background-color: var(---blue-gray);
|
||||
}
|
||||
|
||||
.write-post h2 {
|
||||
|
@ -102,7 +176,7 @@ body {
|
|||
|
||||
a {
|
||||
text-decoration: none;
|
||||
color: var(--background-color);
|
||||
color: var(--blue-gray);
|
||||
}
|
||||
|
||||
.pfp {
|
||||
|
@ -118,7 +192,7 @@ a {
|
|||
|
||||
.post:not(.block) {
|
||||
margin-top: calc(var(--header-height) / 4);
|
||||
border-left: var(--comment-column-width) solid var(--accent-color);
|
||||
border-left: var(--comment-column-width) solid var(--sky-blue);
|
||||
padding-left: calc(var(--header-height) / 2 - var(--comment-column-width));
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue