Skip to content

Commit

Permalink
ui changes, ux / flow updates
Browse files Browse the repository at this point in the history
Made the buttons appear sequentially, added some random ui ideas
  • Loading branch information
codeAndie committed Oct 18, 2024
1 parent 9a6d91f commit ff5f293
Show file tree
Hide file tree
Showing 3 changed files with 215 additions and 54 deletions.
106 changes: 106 additions & 0 deletions src/App.css
Original file line number Diff line number Diff line change
@@ -1,3 +1,42 @@
@keyframes pulse {
0% {
transform: scale(1);
}
50% {
transform: scale(1.1);
}
100% {
transform: scale(1);
}
}

@keyframes bounce {
0%, 100% {
transform: translateY(0);
}
50% {
transform: translateY(-30px);
}
}

@keyframes move {
0% {
transform: translate(0, 0);
}
25% {
transform: translate(100px, -100px);
}
50% {
transform: translate(200px, 0);
}
75% {
transform: translate(100px, 100px);
}
100% {
transform: translate(0, 0);
}
}

.App {
font-family: Arial, sans-serif;
text-align: center;
Expand All @@ -24,3 +63,70 @@ button:hover {
audio {
margin-top: 15px;
}

.circle-button {
width: 200px; /* Adjust size as needed */
height: 200px; /* Adjust size as needed */
background-color: red; /* Red background color */
color: white; /* White text color */
border: none; /* Remove border */
border-radius: 50%; /* Make it circular */
font-size: 32px; /* Adjust font size as needed */
display: flex; /* Use flexbox for centering */
align-items: center; /* Center content vertically */
justify-content: center; /* Center content horizontally */
cursor: pointer; /* Pointer cursor on hover */
transition: background-color 0.3s; /* Smooth transition for hover effect */
}

.circle-button:hover {
background-color: darkred; /* Darker red on hover */
}

.center-screen {
display: flex;
justify-content: center;
align-items: center;
height: 50vh; /* Full viewport height */
}

.pulse {
animation: pulse 1s infinite; /* Apply the pulse animation */
}

.vertical-stack {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 1rem; /* Adjust the gap between elements as needed */
}

.secret-container {
padding: 20px; /* Add padding inside the container */
border-radius: 15px; /* Rounded corners */
background-color: #f9f9f9; /* Light background color */
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); /* Subtle shadow for depth */
border: 2px solid #e0e0e0; /* Light border */
position: relative; /* For positioning pseudo-elements */
overflow: hidden; /* Hide overflow for pseudo-elements */
animation: bounce 5s infinite, move 10s infinite; /* Apply bounce and move animations */
}

.secret-container::before,
.secret-container::after {
content: '';
position: absolute;
width: 100%;
height: 100%;
top: 0;
left: 0;
background: linear-gradient(45deg, rgba(255, 0, 0, 0.1), rgba(0, 0, 255, 0.1));
mix-blend-mode: multiply;
pointer-events: none; /* Allow clicks to pass through */
z-index: 1; /* Ensure it's above the content */
}

.secret-container::after {
background: linear-gradient(-45deg, rgba(0, 255, 0, 0.1), rgba(255, 255, 0, 0.1));
}
7 changes: 3 additions & 4 deletions src/App.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import React from 'react';
import AudioRecorder from './AudioRecorder'; // Import the component
import React from "react";
import AudioRecorder from "./AudioRecorder"; // Import the component

function App() {
return (
<div className="App" style={{ textAlign: 'center', marginTop: '50px' }}>
<h1>Welcome to Audio Recorder App</h1>
<div className="App" style={{ textAlign: "center", marginTop: "50px" }}>
<AudioRecorder /> {/* Render the AudioRecorder component */}
</div>
);
Expand Down
156 changes: 106 additions & 50 deletions src/AudioRecorder.js
Original file line number Diff line number Diff line change
@@ -1,25 +1,30 @@
import React, { useState, useRef } from "react";
import { Loader2, Mic, Send, PlayCircle, AlertCircle } from "lucide-react";
import "./App.css"; // Ensure this line is present

const AudioRecorder = () => {
const [isRecording, setIsRecording] = useState(false);
const [recording, setRecording] = useState(null);
const [audioUrl, setAudioUrl] = useState(null);
const [isSubmitting, setIsSubmitting] = useState(false);
const [isSubmitted, setIsSubmitted] = useState(false);
const [isLoading, setIsLoading] = useState(false);
const [randomAudioUrl, setRandomAudioUrl] = useState(null);
const [error, setError] = useState(null);
const mediaRecorderRef = useRef(null);
const audioChunksRef = useRef([]);
const [showSecret, setShowSecret] = useState(false);
const [showAudio, setShowAudio] = useState(false);

const startRecording = async () => {
console.log("Recording started");
try {
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
mediaRecorderRef.current = new MediaRecorder(stream);

mediaRecorderRef.current.ondataavailable = (event) => {
if (event.data.size > 0) audioChunksRef.current.push(event.data);
};

console.log("audio good");
mediaRecorderRef.current.onstop = () => {
const audioBlob = new Blob(audioChunksRef.current, {
type: "audio/webm",
Expand All @@ -38,15 +43,17 @@ const AudioRecorder = () => {
};

const stopRecording = () => {
console.log("Recording stopped");
mediaRecorderRef.current?.stop();
setIsRecording(false);
setShowAudio(true);
};

const sendAudioToAzureFunction = async () => {
if (!audioUrl) return;

setIsSubmitting(true);
setError(null);
setShowAudio(false);
const formData = new FormData();
const audioBlob = await fetch(audioUrl).then((r) => r.blob());
formData.append("audio", audioBlob, "recording.webm");
Expand All @@ -71,12 +78,14 @@ const AudioRecorder = () => {
setError("Failed to upload audio");
} finally {
setIsSubmitting(false);
setIsSubmitted(true);
}
};

const getRandomAudio = async () => {
setIsLoading(true);
setError(null);
setShowSecret(true);
try {
const response = await fetch(
"https://labracadabra-confessional.azurewebsites.net/api/loadRandomAudioBlob?"
Expand All @@ -101,59 +110,101 @@ const AudioRecorder = () => {
}
};

const handleDelete = () => {
setRecording(null);
setIsSubmitted(false);
setShowSecret(false);
setShowAudio(false);
};

const handleRestart = () => {
setRecording(null);
setIsSubmitted(false);
setShowSecret(false);
setAudioUrl(null); // Clear the recorded audio
};

const handleSubmit = () => {
setIsSubmitting(true);
// Logic to submit the recording to the database
// Simulate a delay for submission
setTimeout(() => {
setIsSubmitting(false);
setIsSubmitted(true);
}, 2000);
};

console.log("audioUrl", audioUrl);
console.log("show audio: ", showAudio);
console.log("issubmitted: ", isSubmitted);

return (
<div className="flex flex-col items-center justify-center min-h-screen bg-gray-100 p-4">
<div className="bg-white shadow-xl rounded-lg p-6 w-full max-w-md">
<h2 className="text-2xl font-bold mb-4 text-center">
Hellium Confessional
</h2>

<div className="flex justify-center mb-4">
<button
onClick={isRecording ? stopRecording : startRecording}
className={`px-4 py-2 rounded-full ${
isRecording
? "bg-red-500 hover:bg-red-600 text-white"
: "bg-blue-500 hover:bg-blue-600 text-white"
}`}
>
{isRecording ? <Mic className="h-6 w-6" /> : "Start Recording"}
</button>
</div>

{audioUrl && (
<div className="mb-4">
<h3 className="font-semibold mb-2">Preview:</h3>
<audio controls src={audioUrl} className="w-full" />
{!recording && !isSubmitted && !isSubmitting && !showAudio && (
<div className="center-screen">
<button
onClick={sendAudioToAzureFunction}
disabled={isSubmitting}
className="mt-2 px-4 py-2 bg-green-500 text-white rounded hover:bg-green-600 disabled:opacity-50 w-full flex justify-center items-center"
onClick={isRecording ? stopRecording : startRecording}
// className={`px-4 py-2 rounded-full ${
className={`circle-button ${isRecording ? "pulse" : ""}`}
>
{isSubmitting ? (
{/* {isRecording ? <Mic className="h-6 w-6" /> : "Start Recording"} */}
{isRecording ? "STOP" : "Record Confession"}
</button>
</div>
)}

{audioUrl && showAudio && (
<div className="center-screen">
<div className="vertical-stack">
<h3 className="font-semibold mb-2">Your secret:</h3>
<div className="secret-container">
<audio controls src={audioUrl} className="w-full" />
</div>
<button onClick={handleDelete}>Try again</button>
<button
onClick={sendAudioToAzureFunction}
disabled={isSubmitting}
className="mt-2 px-4 py-2 bg-green-500 text-white rounded hover:bg-green-600 disabled:opacity-50 w-full flex justify-center items-center"
>
{/* {isSubmitting ? (
<Loader2 className="h-5 w-5 animate-spin" />
) : (
<Send className="h-5 w-5 mr-2" />
)}
{isSubmitting ? "Submitting..." : "Submit Recording"}
</button>
)} */}
{isSubmitting ? "Submitting..." : "Submit secret"}
</button>
</div>
</div>
)}

<div className="mt-6">
<button
onClick={getRandomAudio}
disabled={isLoading}
className="px-4 py-2 bg-purple-500 text-white rounded hover:bg-purple-600 disabled:opacity-50 w-full flex justify-center items-center"
>
{isLoading ? (
<Loader2 className="h-5 w-5 animate-spin" />
) : (
<PlayCircle className="h-5 w-5 mr-2" />
)}
{isLoading ? "Loading..." : "Play Random Recording"}
</button>
</div>
{isSubmitting && (
<div className="mt-6">
<p>Submitting...</p>
</div>
)}

{isSubmitted && !showAudio && !showSecret && (
<div className="mt-6">
<p>Recording submitted successfully!</p>
<button
onClick={getRandomAudio}
disabled={isLoading}
className="px-4 py-2 bg-purple-500 text-white rounded hover:bg-purple-600 disabled:opacity-50 w-full flex justify-center items-center"
>
{/* {isLoading ? (
<Loader2 className="h-5 w-5 animate-spin" />
) : (
<PlayCircle className="h-5 w-5 mr-2" />
)} */}
{isLoading ? "Loading..." : "Get secret"}
</button>
</div>
)}

{error && (
<div className="mt-4 p-2 bg-red-100 border border-red-400 text-red-700 rounded flex items-center">
Expand All @@ -162,15 +213,20 @@ const AudioRecorder = () => {
</div>
)}

{randomAudioUrl && !error && (
<div className="mt-4">
<h3 className="font-semibold mb-2">Random Recording:</h3>
<audio
controls
src={randomAudioUrl}
className="w-full"
onError={() => setError("Failed to load audio")}
/>
{randomAudioUrl && !error && showSecret && (
<div className="center-screen">
<div className="vertical-stack">
<div className="secret-container">
<h3 className="font-semibold mb-2">Someone else's secret...</h3>
<audio
controls
src={randomAudioUrl}
className="w-full"
onError={() => setError("Failed to load audio")}
/>
</div>
<button onClick={handleRestart}>Add a new secret</button>
</div>
</div>
)}
</div>
Expand Down

0 comments on commit ff5f293

Please sign in to comment.