mirror of
https://github.com/MinazukiAmane/shortlink.git
synced 2025-03-16 11:05:58 +08:00
242 lines
5.9 KiB
TypeScript
242 lines
5.9 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 muted loop>
|
|
<source src="/video/video.webm" type="video/webm" />
|
|
</BackgroundVideo>
|
|
<BackgroundAudio ref={audioRef} autoPlay loop>
|
|
<source src="/sounds/music.mp3" type="audio/mpeg" />
|
|
</BackgroundAudio>
|
|
<ProgressContainer>
|
|
<LoadingItem>{currentLoadingItem}</LoadingItem>
|
|
<ProgressBarContainer>
|
|
<ProgressBar style={{ width: `${progress}%` }} />
|
|
</ProgressBarContainer>
|
|
<ProgressText>{progress.toFixed(2)}%</ProgressText>
|
|
</ProgressContainer>
|
|
</LoadingContainer>
|
|
) : (
|
|
<>
|
|
<VideoBackground 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.
|
|
</VideoBackground>
|
|
<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;
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
height: 100vh;
|
|
width: 100%;
|
|
overflow: hidden;
|
|
`;
|
|
|
|
const VideoBackground = 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 Button = styled.button`
|
|
padding: 10px 20px;
|
|
`;
|
|
|
|
const ProgressContainer = styled.div`
|
|
position: absolute;
|
|
bottom: 20px;
|
|
width: 80%;
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
background: rgba(0, 0, 0, 0.5);
|
|
padding: 10px;
|
|
border-radius: 10px;
|
|
`;
|
|
|
|
const ProgressBarContainer = styled.div`
|
|
width: 100%;
|
|
background: rgba(255, 255, 255, 0.2);
|
|
border-radius: 5px;
|
|
overflow: hidden;
|
|
`;
|
|
|
|
const ProgressBar = styled.div`
|
|
height: 10px;
|
|
background: linear-gradient(to right, #4caf50, #81c784);
|
|
transition: width 0.5s;
|
|
`;
|
|
|
|
const ProgressText = styled.span`
|
|
margin-top: 10px;
|
|
font-size: 14px;
|
|
color: white;
|
|
`;
|
|
|
|
const LoadingContainer = styled.div`
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
justify-content: center;
|
|
width: 100%;
|
|
height: 100%;
|
|
position: relative;
|
|
`;
|
|
|
|
const LoadingItem = styled.div`
|
|
font-size: 14px;
|
|
margin-bottom: 10px;
|
|
color: white;
|
|
`;
|
|
|
|
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 BackgroundVideo = styled.video`
|
|
position: absolute;
|
|
top: 0;
|
|
left: 0;
|
|
width: 100%;
|
|
height: 100%;
|
|
object-fit: cover;
|
|
z-index: -1;
|
|
`;
|
|
|
|
const BackgroundAudio = styled.audio`
|
|
display: block;
|
|
`;
|
|
|
|
export default Home;
|