mirror of
https://github.com/MinazukiAmane/shortlink.git
synced 2025-03-16 09:25:58 +08:00
change from use video and audio on the loading now only use di video, and change the styling for loading
232 lines
5.6 KiB
TypeScript
232 lines
5.6 KiB
TypeScript
import { useState, useEffect, useRef } from 'react';
|
|
import styled from '@emotion/styled';
|
|
|
|
const Home = () => {
|
|
const [url, setUrl] = useState('');
|
|
const [shortlink, setShortlink] = useState('');
|
|
const [initialLoading, setInitialLoading] = useState(true);
|
|
const [shortlinkLoading, setShortlinkLoading] = useState(false);
|
|
const [progress, setProgress] = useState(0);
|
|
const [loadingItems, setLoadingItems] = useState([
|
|
"Loading assets...",
|
|
"Initializing components...",
|
|
"Fetching data...",
|
|
"Setting up the environment...",
|
|
"Almost there..."
|
|
]);
|
|
const [currentLoadingItem, setCurrentLoadingItem] = useState(loadingItems[0]);
|
|
const audioRef = useRef<HTMLAudioElement>(null);
|
|
|
|
useEffect(() => {
|
|
if (audioRef.current) {
|
|
audioRef.current.play().catch(error => {
|
|
console.error('Audio play failed:', error);
|
|
});
|
|
}
|
|
|
|
const interval = setInterval(() => {
|
|
setProgress((oldProgress) => {
|
|
if (oldProgress >= 100) {
|
|
clearInterval(interval);
|
|
setInitialLoading(false);
|
|
return 100;
|
|
}
|
|
const diff = Math.random() * 10;
|
|
const newProgress = Math.min(oldProgress + diff, 100);
|
|
if (newProgress < 100) {
|
|
const currentItemIndex = Math.floor(newProgress / 20);
|
|
setCurrentLoadingItem(loadingItems[currentItemIndex]);
|
|
}
|
|
return newProgress;
|
|
});
|
|
}, 500);
|
|
|
|
return () => clearInterval(interval);
|
|
}, [loadingItems]);
|
|
|
|
const createShortlink = async () => {
|
|
setShortlinkLoading(true);
|
|
try {
|
|
const response = await fetch(process.env.NEXT_PUBLIC_API_URL!, {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
},
|
|
body: JSON.stringify({ url }),
|
|
});
|
|
const text = await response.text();
|
|
const shortlinkUrl = text.match(/https?:\/\/[^\s]+/g)?.[0] || '';
|
|
setShortlink(shortlinkUrl);
|
|
} catch (error) {
|
|
console.error('Error creating shortlink:', error);
|
|
}
|
|
setShortlinkLoading(false);
|
|
};
|
|
|
|
return (
|
|
<Container>
|
|
{initialLoading ? (
|
|
<LoadingContainer>
|
|
<BackgroundVideo autoPlay loop>
|
|
<source src="/video/video.webm" type="video/webm" />
|
|
</BackgroundVideo>
|
|
<ProgressContainer>
|
|
<LoadingItem>{currentLoadingItem}</LoadingItem>
|
|
<ProgressBarContainer>
|
|
<ProgressBar style={{ background: `linear-gradient(to right, #f0c8a0 0% ${progress - 5}%, #f0dcc8 ${progress}%, transparent ${progress}%)` }}/>
|
|
</ProgressBarContainer>
|
|
<ProgressText>{progress.toFixed(2)}%</ProgressText>
|
|
</ProgressContainer>
|
|
</LoadingContainer>
|
|
) : (
|
|
<>
|
|
<BackgroundVideo autoPlay muted loop>
|
|
<source
|
|
src="/video/dekstop.mp4"
|
|
type="video/mp4"
|
|
media="(min-width: 768px)"
|
|
/>
|
|
<source
|
|
src="/video/phone.mp4"
|
|
type="video/mp4"
|
|
media="(max-width: 767px)"
|
|
/>
|
|
Your browser does not support the video tag.
|
|
</BackgroundVideo>
|
|
<Content>
|
|
<h1>Create Shortlink</h1>
|
|
<Input
|
|
type="text"
|
|
placeholder="Enter URL"
|
|
value={url}
|
|
onChange={(e) => setUrl(e.target.value)}
|
|
/>
|
|
<Button onClick={createShortlink} disabled={shortlinkLoading}>
|
|
Create Shortlink
|
|
</Button>
|
|
{shortlinkLoading && (
|
|
<ShortlinkLoadingContainer>
|
|
<ProgressText>Loading...</ProgressText>
|
|
</ShortlinkLoadingContainer>
|
|
)}
|
|
{shortlink && (
|
|
<div>
|
|
<h2>Shortlink:</h2>
|
|
<a href={shortlink} target="_blank" rel="noopener noreferrer">
|
|
{shortlink}
|
|
</a>
|
|
</div>
|
|
)}
|
|
</Content>
|
|
</>
|
|
)}
|
|
</Container>
|
|
);
|
|
};
|
|
|
|
const Container = styled.div`
|
|
position: relative;
|
|
|
|
height: 100vh;
|
|
width: 100%;
|
|
overflow: hidden;
|
|
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
`;
|
|
|
|
const BackgroundVideo = styled.video`
|
|
position: absolute;
|
|
top: 0;
|
|
left: 0;
|
|
width: 100%;
|
|
height: 100%;
|
|
object-fit: cover;
|
|
z-index: -1;
|
|
`;
|
|
|
|
const Content = styled.div`
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
background: rgba(255, 255, 255, 0.8);
|
|
padding: 20px;
|
|
border-radius: 10px;
|
|
`;
|
|
|
|
const Input = styled.input`
|
|
padding: 10px;
|
|
width: 300px;
|
|
margin-bottom: 20px;
|
|
`;
|
|
|
|
const ShortlinkLoadingContainer = styled.div`
|
|
margin-top: 20px;
|
|
width: 80%;
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
background: rgba(0, 0, 0, 0.5);
|
|
padding: 10px;
|
|
border-radius: 10px;
|
|
`;
|
|
|
|
const Button = styled.button`
|
|
padding: 10px 20px;
|
|
`;
|
|
|
|
const LoadingContainer = styled.div`
|
|
width: 100%;
|
|
height: 100%;
|
|
|
|
color: white;
|
|
font-size: 18px;
|
|
`;
|
|
|
|
const ProgressContainer = styled.div`
|
|
position: absolute;
|
|
width: 100%;
|
|
bottom: 40px;
|
|
padding: 0 20%;
|
|
box-sizing: border-box;
|
|
|
|
display: grid;
|
|
grid-template-areas:
|
|
'text . perc'
|
|
'bar bar bar'
|
|
;
|
|
grid-template-columns: auto 1fr auto;
|
|
|
|
z-index: 2;
|
|
`;
|
|
|
|
const ProgressBarContainer = styled.div`
|
|
grid-area: bar;
|
|
width: 100%;
|
|
|
|
background: rgba(240, 220, 200, 6%);
|
|
border: 1px solid rgba(255, 255, 255, 8%);
|
|
border-radius: 5px;
|
|
overflow: hidden;
|
|
`;
|
|
|
|
const ProgressBar = styled.div`
|
|
height: 0.6em;
|
|
|
|
background: transparent;
|
|
transition: width 0.5s;
|
|
`;
|
|
|
|
const ProgressText = styled.span`
|
|
grid-area: perc;
|
|
margin-right: 8px;
|
|
`;
|
|
|
|
const LoadingItem = styled.div`
|
|
grid-area: text;
|
|
margin-left: 8px;
|
|
`;
|
|
|
|
export default Home;
|