diff --git a/client/src/pages/Home/Home.jsx b/client/src/pages/Home/Home.jsx
index 6ac15ec..62eeb46 100644
--- a/client/src/pages/Home/Home.jsx
+++ b/client/src/pages/Home/Home.jsx
@@ -1,13 +1,164 @@
import "./styles.sass";
import {StateContext} from "@/common/contexts/StateContext";
-import {useContext} from "react";
+import {useContext, useState, useEffect, useRef} from "react";
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+import { faMusic } from '@fortawesome/free-solid-svg-icons';
+
+const songs = ["Twinkle Twinkle Little Star", "Happy Birthday", "Jingle Bells", "Mary Had a Little Lamb", "Old MacDonald Had a Farm"];
export const Home = () => {
const {setCurrentState} = useContext(StateContext);
+ const [frequency, setFrequency] = useState(440);
+ const [isPlaying, setIsPlaying] = useState(false);
+ const [currentSong, setCurrentSong] = useState(songs[Math.floor(Math.random() * songs.length)]);
+ const [dragging, setDragging] = useState(false);
+ const audioContextRef = useRef(null);
+ const oscillatorRef = useRef(null);
+ const gainNodeRef = useRef(null);
+ const sliderRef = useRef(null);
+ const [messages, setMessages] = useState([]);
+ const [inputValue, setInputValue] = useState("");
+ const messageEndRef = useRef(null);
+
+ const startAudio = () => {
+ if (!audioContextRef.current) {
+ audioContextRef.current = new (window.AudioContext || window.webkitAudioContext)();
+ }
+ if (!oscillatorRef.current) {
+ oscillatorRef.current = audioContextRef.current.createOscillator();
+ oscillatorRef.current.type = 'sine';
+ oscillatorRef.current.frequency.setValueAtTime(frequency, audioContextRef.current.currentTime);
+
+ gainNodeRef.current = audioContextRef.current.createGain();
+ gainNodeRef.current.gain.setValueAtTime(0.5, audioContextRef.current.currentTime);
+
+ oscillatorRef.current.connect(gainNodeRef.current);
+ gainNodeRef.current.connect(audioContextRef.current.destination);
+ oscillatorRef.current.start();
+ } else {
+ oscillatorRef.current.frequency.setValueAtTime(frequency, audioContextRef.current.currentTime);
+ }
+ setIsPlaying(true);
+ };
+
+ const stopAudio = () => {
+ if (oscillatorRef.current) {
+ oscillatorRef.current.stop();
+ oscillatorRef.current.disconnect();
+ oscillatorRef.current = null;
+ }
+ setIsPlaying(false);
+ };
+
+ const handleMouseDown = (e) => {
+ setDragging(true);
+ startAudio();
+ handleFrequencyChange(e);
+ };
+
+ const handleMouseUp = () => {
+ setDragging(false);
+ stopAudio();
+ };
+
+ const handleFrequencyChange = (e) => {
+ if (isPlaying || dragging) {
+ const rect = sliderRef.current.getBoundingClientRect();
+ const x = e.clientX - rect.left; // x position within the element.
+ const newFrequency = 20 + (x / rect.width) * 1980; // Scale to frequency range
+ setFrequency(newFrequency);
+ }
+ };
+
+ useEffect(() => {
+ if (isPlaying) {
+ if (oscillatorRef.current) {
+ oscillatorRef.current.frequency.setValueAtTime(frequency, audioContextRef.current.currentTime);
+ }
+ }
+ }, [frequency, isPlaying]);
+
+ useEffect(() => {
+ messageEndRef.current?.scrollIntoView({ behavior: "smooth" });
+ }, [messages]);
+
+ const handleSendMessage = () => {
+ if (inputValue.trim()) {
+ setMessages([...messages, { sender: "User", text: inputValue }]);
+ setInputValue("");
+ }
+ };
return (
-
ToneGuessr
+
+
+
+
+
+
+
+
Play this song:
+
+

+
+
{currentSong}
+
A beautiful classic song for you to play on the Otamatone.
+
+
+
+
+
+
+ {messages.map((message, index) => (
+
+ {message.sender}:
+ {message.text}
+
+ ))}
+
+
+
+ setInputValue(e.target.value)}
+ onKeyPress={(e) => e.key === 'Enter' && handleSendMessage()}
+ placeholder="Type your message..."
+ />
+
+
+
+
+
);
-}
+}
\ No newline at end of file
diff --git a/client/src/pages/Home/styles.sass b/client/src/pages/Home/styles.sass
index 5eaa76f..3c42f9e 100644
--- a/client/src/pages/Home/styles.sass
+++ b/client/src/pages/Home/styles.sass
@@ -1,8 +1,257 @@
.home-page
display: flex
+ flex-direction: column
align-items: center
justify-content: center
height: 100vh
+ background: linear-gradient(135deg, #0f2027, #203a43, #2c5364)
+ padding: 20px
+ user-select: none
+ overflow: hidden
+ position: relative
- h2
- font-size: 48pt
\ No newline at end of file
+ .background-elements
+ position: absolute
+ top: 0
+ left: 0
+ width: 100%
+ height: 100%
+ overflow: hidden
+ z-index: 0
+
+ .music-note
+ position: absolute
+ font-size: 24pt
+ color: rgba(255, 255, 255, 0.5)
+ animation: float-notes 5s infinite ease-in-out
+
+ &.note-1
+ top: 20%
+ left: 30%
+
+ &.note-2
+ top: 60%
+ left: 80%
+
+ &.note-3
+ top: 90%
+ left: 50%
+
+ @keyframes float-notes
+ 0%
+ transform: translateY(0)
+ 50%
+ transform: translateY(-10px)
+ 100%
+ transform: translateY(0)
+
+ .main-content
+ display: flex
+ flex-direction: row
+ align-items: flex-start
+ justify-content: center
+ width: 100%
+ padding: 20px
+ z-index: 1
+
+ .song-display
+ display: flex
+ flex-direction: column
+ align-items: center
+ justify-content: center
+ width: 50%
+ margin-right: 20px
+ color: #fff
+ text-align: center
+
+ h2
+ font-size: 36pt
+ color: #fff
+ margin-bottom: 20px
+
+ .song-card
+ display: flex
+ flex-direction: row
+ align-items: center
+ background-color: rgba(255, 255, 255, 0.1)
+ padding: 20px
+ border-radius: 20px
+ box-shadow: 0 4px 8px rgba(0, 0, 0, 0.5)
+ backdrop-filter: blur(10px)
+ border: 1px solid rgba(255, 255, 255, 0.2)
+ max-width: 500px
+
+ img
+ width: 100px
+ height: 100px
+ border-radius: 10px
+ margin-right: 20px
+
+ .song-info
+ display: flex
+ flex-direction: column
+ align-items: flex-start
+
+ .song-name
+ font-size: 24pt
+ color: #fff
+ margin-bottom: 10px
+
+ .song-description
+ font-size: 14pt
+ color: #aaa
+
+ .chat-window
+ width: 50%
+ height: 400px
+ background: rgba(255, 255, 255, 0.1)
+ backdrop-filter: blur(10px)
+ border-radius: 10px
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1)
+ border: 1px solid rgba(255, 255, 255, 0.2)
+ display: flex
+ flex-direction: column
+ overflow: hidden
+
+ .chat-header
+ display: flex
+ align-items: center
+ padding: 10px
+ background: rgba(30, 30, 30, 0.5)
+ border-bottom: 1px solid rgba(255, 255, 255, 0.2)
+
+ .account-icon
+ width: 30px
+ height: 30px
+ background: url('https://place-hold.it/100x100') no-repeat center
+ background-size: cover
+ border-radius: 50%
+ margin-right: 10px
+
+ .chat-title
+ font-size: 16pt
+ color: #fff
+
+ .chat-messages
+ flex: 1
+ padding: 10px
+ overflow-y: auto
+ color: #fff
+
+ .message
+ margin-bottom: 10px
+
+ .message-sender
+ font-weight: bold
+
+ .message-text
+ margin-left: 10px
+
+ .chat-input
+ display: flex
+ padding: 10px
+ background: rgba(30, 30, 30, 0.5)
+ border-top: 1px solid rgba(255, 255, 255, 0.2)
+
+ input
+ flex: 1
+ padding: 10px
+ border: none
+ border-radius: 5px
+ outline: none
+ background: rgba(255, 255, 255, 0.2)
+ color: #fff
+
+ button
+ margin-left: 10px
+ padding: 10px
+ background-color: #203a43
+ color: #fff
+ border: none
+ border-radius: 5px
+ cursor: pointer
+
+ &:hover
+ background-color: #1e1e1e
+
+ .otamatone-container
+ display: flex
+ justify-content: center
+ align-items: center
+ position: fixed
+ left: 0
+ right: 0
+ bottom: 0
+ padding: 20px
+ background-color: rgba(30, 30, 30, 0.5)
+ backdrop-filter: blur(10px)
+ border-radius: 20px
+ margin: 20px
+ z-index: 1
+
+ .otamatone
+ display: flex
+ flex-direction: row
+ align-items: center
+ cursor: pointer
+ padding: 10px
+ width: 100%
+
+ .otamatone-neck
+ flex: 1
+ height: 20px
+ background: linear-gradient(135deg, #000, #444)
+ border-radius: 10px
+ position: relative
+
+ .frequency-indicator
+ position: absolute
+ top: -10px
+ width: 20px
+ height: 20px
+ background-color: #ff0000
+ border-radius: 50%
+ transform: translateX(-50%)
+
+ .note-marker
+ position: absolute
+ top: -30px
+ font-size: 24pt
+ color: #fff
+
+ .otamatone-face
+ width: 100px
+ height: 100px
+ background: radial-gradient(circle, #fff, #ddd)
+ border-radius: 50%
+ display: flex
+ flex-direction: column
+ align-items: center
+ justify-content: center
+ position: relative
+ box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2)
+
+ .otamatone-eyes
+ display: flex
+ justify-content: space-between
+ width: 60%
+ position: absolute
+ top: 30px
+
+ .eye
+ width: 15px
+ height: 15px
+ background-color: #000
+ border-radius: 50%
+
+ .left-eye
+ margin-right: 10px
+
+ .right-eye
+ margin-left: 10px
+
+ .otamatone-mouth
+ background-color: #000
+ border-radius: 50%
+ position: absolute
+ bottom: 10px
\ No newline at end of file