-
-
-
Meeting Roulette
--
-
-
- - Meeting started at: {{ timeText(startedAt, 2) }} - -
- - Meeting duration so far: {{ timeText(elapsedTime) }} - -
- - Remaining meeting time: {{ timeText(totalRemainingTime) }} - -
- - End estimated at: {{ timeText(estimatedEnd, 2) }} - -
- - Total meeting time: {{ timeText(totalTime) }} - -
- - - -
-
-
+
+
+
+
-
+
+
+ Meeting Roulette
+
+ 🎡 Spin your meetings
+
+
+ {{ timerParts(0) }}
+ {{ timerParts(1) }}
+ :
+ {{ timerParts(2) }}
+ :
+ {{ timerParts(3) }}
+
+
+
+
+
- - - {{ timerText() }} - -
-
-
- Current topic: {{ showSelected ? selectedData.text : '???' }}
-- click to spin -
-
-
+
+
+
+
+
+
+
+ Theme
+
+ -
+
- + + +
-
+
+
+
diff --git a/main.js b/main.js
index 6064add..c05f080 100644
--- a/main.js
+++ b/main.js
@@ -1,3 +1,37 @@
+const DAISYUI_THEMES = [
+ "light",
+ "dark",
+ "cupcake",
+ "bumblebee",
+ "emerald",
+ "corporate",
+ "synthwave",
+ "retro",
+ "cyberpunk",
+ "valentine",
+ "halloween",
+ "garden",
+ "forest",
+ "aqua",
+ "pastel",
+ "fantasy",
+ "luxury",
+ "dracula",
+ "cmyk",
+ "autumn",
+ "business",
+ "acid",
+ "lemonade",
+ "night",
+ "coffee",
+ "winter",
+ "dim",
+ "nord",
+ "sunset",
+ "caramellatte",
+ "abyss",
+];
+
let app = {
data() {
return {
@@ -15,10 +49,12 @@ let app = {
meetingStart: new Date(),
elapsedTime: 0,
initialSpin: true,
- initialColor: Math.random() * 360,
+ initialColor: Math.floor(Math.random() * 4),
rid: 0,
beepTimer: undefined,
sound: undefined,
+ themes: DAISYUI_THEMES,
+ currentTheme: "light",
};
},
watch: {
@@ -43,9 +79,7 @@ let app = {
return this.elapsedTime + this.totalRemainingTime;
},
totalExpectedTime() {
- return this.data
- .map((item) => item.time)
- .reduce((a, b) => a + b, 0);
+ return this.data.map((item) => item.time).reduce((a, b) => a + b, 0);
},
totalRemainingTime() {
return this.filteredData
@@ -62,7 +96,9 @@ let app = {
estimatedEnd() {
const end = new Date(this.meetingStart.getTime());
const timerDelta = (this.timerEnd - this.date) / (1000 * 60);
- end.setMinutes(end.getMinutes() + this.totalTime - (this.timerStarted ? timerDelta : 0));
+ end.setMinutes(
+ end.getMinutes() + this.totalTime - (this.timerStarted ? timerDelta : 0)
+ );
return end.getHours() * 60 + end.getMinutes();
},
svgData() {
@@ -75,6 +111,12 @@ let app = {
const angleDeg = (360 * ratio) % 360;
const textScale = this.textScale(item.text, angleRad);
totalAngle += angleDeg;
+ const colorIndex =
+ ((index == this.filteredData.length - 1 && index % 4 == 0 ? 1 : 0) +
+ index +
+ this.initialColor) %
+ 4;
+ const color = ["primary", "secondary", "accent", "neutral"][colorIndex];
return {
id: item.id,
text: item.text,
@@ -86,7 +128,8 @@ let app = {
angleRad / 2
)} ${Math.sin(angleRad / 2)} z`,
transform: `rotate(${totalAngle - angleDeg / 2}, 0, 0)`,
- color: `hsl(${this.initialColor + 100 * index} 80% 50%)`,
+ textStyle: `fill: var(--color-${color}-content)`,
+ backgroundStyle: `fill: var(--color-${color})`,
from: totalAngle - angleDeg,
to: totalAngle,
};
@@ -103,22 +146,36 @@ let app = {
overtime() {
return this.timerStarted && this.timerEnd - new Date() <= 0;
},
- timerText() {
+ timerParts(i) {
const delta = this.timerStarted
? Math.floor((this.timerEnd - new Date()) / 1000)
- : (this.showSelected
- ? this.selectedData.time * 60
- : 0);
- return `${delta < 0 ? "-" : ""}${String(
- Math.floor(Math.abs(delta) / 60)
- ).padStart(2, "0")}:${String(Math.abs(delta) % 60).padStart(2, "0")}`;
+ : this.showSelected
+ ? this.selectedData.time * 60
+ : 0;
+ if (i == 0) {
+ return delta < 0 ? "-" : "";
+ }
+ const hours = Math.floor(Math.abs(delta) / 3600);
+ if (i == 1) {
+ return String(hours).padStart(2, "0");
+ }
+ const minutes = Math.floor(Math.abs(delta) / 60 - hours * 60);
+ if (i == 2) {
+ return String(minutes).padStart(2, "0");
+ }
+ const seconds = Math.abs(delta) % 60;
+ return String(seconds).padStart(2, "0");
},
beep() {
this.sound.play();
},
timeText(minutes, padHours = 0) {
if (minutes >= 60 || padHours > 0) {
- return `${Math.floor(minutes / 60).toFixed(0).padStart(padHours, "0")}h${(minutes % 60).toFixed(0).padStart(2, "0")}`;
+ return `${Math.floor(minutes / 60)
+ .toFixed(0)
+ .padStart(padHours, "0")}h${(minutes % 60)
+ .toFixed(0)
+ .padStart(2, "0")}`;
} else {
return `${(minutes % 60).toFixed(0).padStart(2, "0")}min`;
}
@@ -173,12 +230,14 @@ let app = {
}
});
if (data.length === 0) {
- return [{
- id: 0,
- text: '?',
- time: 1,
- disabled: false,
- }];
+ return [
+ {
+ id: 0,
+ text: "?",
+ time: 1,
+ disabled: false,
+ },
+ ];
}
return data;
},
@@ -217,7 +276,7 @@ let app = {
},
setCookie(cname, cvalue, exdays) {
const d = new Date();
- d.setTime(d.getTime() + (exdays * 24 * 60 * 60 * 1000));
+ d.setTime(d.getTime() + exdays * 24 * 60 * 60 * 1000);
let expires = "expires=" + d.toUTCString();
console.log(cname + "=" + cvalue + "; path=/; " + expires);
document.cookie = cname + "=" + cvalue + "; path=/; " + expires;
@@ -225,7 +284,7 @@ let app = {
getCookie(cname, defaultValue) {
let name = cname + "=";
let decodedCookie = decodeURIComponent(document.cookie);
- let ca = decodedCookie.split(';');
+ let ca = decodedCookie.split(";");
for (let i = 0; i < ca.length; i++) {
let c = ca[i];
while (c.charAt(0) == " ") {
@@ -237,17 +296,24 @@ let app = {
}
return defaultValue;
},
+ setTheme(value) {
+ this.currentTheme = value;
+ this.setCookie("theme", this.currentTheme);
+ },
},
mounted: function () {
console.log("app mounted");
this.sound = new Audio("./sound.wav");
this.rawData = atob(this.getCookie("rawData", btoa(this.rawData)));
+ this.currentTheme = this.getCookie("theme", "light");
this.data = this.getData();
setTimeout(this.showApp);
setInterval(() => {
this.rid = Math.random();
if (this.timerStarted) {
- document.title = this.timerText();
+ document.title = `${this.timerParts(0)}${this.timerParts(
+ 1
+ )}:${this.timerParts(2)}:${this.timerParts(3)}`;
}
this.elapsedTime = (new Date() - this.meetingStart) / (1000 * 60);
this.date = new Date();
diff --git a/style.css b/style.css
index 9184782..0fa68d4 100644
--- a/style.css
+++ b/style.css
@@ -1,141 +1,13 @@
-/*
-=================================================
-https://www.joshwcomeau.com/css/custom-css-reset/
-=================================================
-*/
-
-/*
- 1. Use a more-intuitive box-sizing model.
-*/
-*,
-*::before,
-*::after {
- box-sizing: border-box;
-}
-/*
- 2. Remove default margin
- */
-* {
- margin: 0;
-}
-/*
- 3. Allow percentage-based heights in the application
- */
-html,
-body {
- height: 100%;
-}
-/*
- Typographic tweaks!
- 4. Add accessible line-height
- 5. Improve text rendering
- */
-body {
- line-height: 1.5;
- -webkit-font-smoothing: antialiased;
-}
-/*
- 6. Improve media defaults
- */
-img,
-picture,
-video,
-canvas,
-svg {
- display: block;
- max-width: 100%;
-}
-/*
- 7. Remove built-in form typography styles
- */
-input,
-button,
-textarea,
-select {
- font: inherit;
-}
-/*
- 8. Avoid text overflows
- */
-p,
-h1,
-h2,
-h3,
-h4,
-h5,
-h6 {
- overflow-wrap: break-word;
-}
-/*
- 9. Create a root stacking context
- */
-#root,
-#__next {
- isolation: isolate;
-}
-
-/*
-=================================================
-CUSTOM STYLE
-=================================================
-*/
-
-#app {
- width: 100vw;
- height: 100vh;
- overflow: hidden;
- position: relative;
- display: flex;
- flex-direction: row;
- justify-content: center;
- align-items: stretch;
- background-color: #eceff1;
- color: #263238;
- font-family: sans-serif;
-}
-
-.panel {
- flex-grow: 2;
- position: relative;
-}
-
-.panel.right,
-.panel.left {
- background-color: #cfd8dc;
- margin: 1em;
- border-radius: 2em;
- padding: 1em;
-}
-
-.panel.middle {
- height: 100%;
- flex-grow: 1;
-}
-
-.panel.middle h1 {
- position: absolute;
- top: 0;
- width: 100%;
- text-align: center;
-}
-
-.panel.middle h2 {
- position: absolute;
- bottom: 0;
- width: 100%;
- text-align: center;
-}
-
-.wheel {
- position: relative;
- height: 80%;
- width: fit-content;
- margin: 10% auto;
+:root {
+ --wheel: color-mix(
+ in oklch,
+ var(--color-base-content) 30%,
+ var(--color-base-100)
+ );
}
.wheel svg {
transition: transform 5s ease-out;
- height: 100%;
}
svg text {
@@ -153,20 +25,10 @@ svg text {
top: 50%;
width: 0;
height: 0;
- border-right: 6vh solid #263238;
+ border-right: 6vh solid
+ color-mix(in oklch, var(--color-base-content) 40%, var(--color-base-100));
border-bottom: 2vh solid transparent;
border-top: 2vh solid transparent;
transform: translateY(-50%);
clear: both;
}
-
-.panel.right textarea {
- background-color: #cfd8dc;
- color: #263238;
- font-family: sans-serif;
- padding: 0.5em;
- border: 1px solid #263238;
- height: 100%;
- width: 100%;
- border-radius: 1em;
-}
+ Current topic: {{ showSelected ? selectedData.text : '???' }}
+
+
+
+
+
+
+
+
+
+ Discuss the current topic
+
+ Enter your topics then click the wheel to spin !
+
+
+ Start timer or click the wheel to spin
+
+