This commit is contained in:
skidoodle 2023-04-09 05:31:08 +02:00
commit 9cf213d556
29 changed files with 3825 additions and 0 deletions

42
src/components/Icon.tsx Normal file
View file

@ -0,0 +1,42 @@
import Link from 'next/link';
import toast from 'react-hot-toast';
import copy from 'copy-to-clipboard';
type Icon = {
children: any;
reference: string;
copyValue?: boolean;
};
const notify = () => {
toast.remove(),
toast.success('Copied to clipboard', {
style: {
background: '#0f1012',
color: '#fff',
fontSize: '1em',
},
});
};
export const Icon = ({ children, reference, copyValue }: Icon) => {
if (copyValue) {
return (
<Link
href={''}
className={`cursor-pointer`}
onClick={() => {
notify(), copy(reference);
}}
>
{children}
</Link>
);
}
return (
<Link href={reference} target='_blank' className={'cursor-pointer'}>
{children}
</Link>
);
};

View file

@ -0,0 +1,30 @@
import { ThemeSwitcher } from '@/components/ThemeSwitcher';
import { NowPlayingCard } from '@/components/SpotifyCard';
import { SocialLayout } from '@/components/SocialLayout';
import { Toaster } from 'react-hot-toast';
import FadeIn from 'react-fade-in';
export const MainLayout = () => {
return (
<>
<ThemeSwitcher />
<FadeIn>
<div className='ml-[10%] mr-[10%]'>
<div className='flex flex-col max-w-3xl mx-auto mb-16 mt-32'>
<h1 className='text-7xl font-bold'>albert</h1>
<p className='text-2xl text-gray-600 dark:text-gray-400 mt-2 font-semibold'>
{Math.floor(
(new Date().getTime() - new Date('2004-07-22').getTime()) /
(1000 * 60 * 60 * 24 * 365.25)
)}
-year-old system administrator
</p>
<SocialLayout />
<NowPlayingCard />
<Toaster position='bottom-center' reverseOrder={false} />
</div>
</div>
</FadeIn>
</>
);
};

View file

@ -0,0 +1,21 @@
import { Icon } from '@/components/Icon';
import { socials } from '@/components/data/Socials';
import React from 'react';
export const SocialLayout = () => {
return (
<>
<div className='grid grid-flow-col w-48 mt-3 text-2xl space-x-8'>
{socials.map((social) => (
<Icon
key={social.id}
reference={social.ref}
copyValue={social.copyValue}
>
{React.createElement(social.icon)}
</Icon>
))}
</div>
</>
);
};

View file

@ -0,0 +1,48 @@
import { truncate } from '@/utils/truncate';
import FadeIn from 'react-fade-in';
import Image from 'next/image';
import useSWR from 'swr';
import SongImage from '@/public/song.webp';
import Link from 'next/link';
export const fetcher = (url: RequestInfo) => fetch(url).then((r) => r.json());
export const NowPlayingCard = () => {
var { data: spotify } = useSWR('/api/spotify', fetcher, {
refreshInterval: 3000,
fallbackData: 'loading',
});
return (
<FadeIn>
<div className='mt-5 focus:outline-none transition duration-300 ease-in-out transform hover:scale-105 p-3 rounded-md border border-gray-800 shadow flex flex-row max-w-sm'>
{spotify.song ? (
<Image
height={45}
width={45}
alt='Song cover art'
src={spotify.song?.image}
/>
) : (
<Image height={45} width={45} alt='Song cover art' src={SongImage} />
)}
<div className='my-auto ml-4'>
<div className='font-semibold text-l sm:text-regular'>
Listening to{' '}
{spotify.song ? (
<Link
href={`${spotify.song.url}`}
target='_blank'
className='text-[#32a866]'
>
{truncate(`${spotify.song.title}`, 20)}
</Link>
) : (
<span className='text-[#32a866]'>nothing</span>
)}
</div>
</div>
</div>
</FadeIn>
);
};

View file

@ -0,0 +1,35 @@
import { useTheme } from 'next-themes';
import { useEffect, useState } from 'react';
import { BsSunFill, BsMoonFill } from 'react-icons/bs';
export const ThemeSwitcher = () => {
const [mounted, setMounted] = useState(false);
const { theme, setTheme } = useTheme();
const toggle = () => {
if (theme === 'dark') {
setTheme('light');
} else {
setTheme('dark');
}
};
useEffect(() => setMounted(true), []);
if (!mounted) return null;
return (
<button
aria-label='Toggle Dark Mode'
type='button'
className='focus:outline-none bg-none xs:bg-gray-200 xs:dark:bg-gray-800 rounded-lg p-3 h-10 w-10 flex items-center justify-center ml-auto'
onClick={() => toggle()}
>
{theme === 'light' ? (
<BsMoonFill style={{ fill: 'black' }} size={300} />
) : (
<BsSunFill size={300} />
)}
</button>
);
};

View file

@ -0,0 +1,45 @@
import { IconType } from 'react-icons/lib';
import {
FaDiscord,
FaEnvelope,
FaGithub,
FaInstagram,
FaSteam,
} from 'react-icons/fa';
type Socials = {
id: number;
ref: string;
icon: IconType;
copyValue?: boolean;
};
export const socials: Array<Socials> = [
{
id: 1,
ref: 'https://github.com/skidoodle',
icon: FaGithub,
},
{
id: 2,
ref: 'https://steamcommunity.com/id/_albert',
icon: FaSteam,
},
{
id: 3,
ref: 'contact@albert.lol',
icon: FaEnvelope,
copyValue: true,
},
{
id: 4,
ref: 'https://www.instagram.com/albertadam_/',
icon: FaInstagram,
},
{
id: 5,
ref: 'albert#8838',
icon: FaDiscord,
copyValue: true,
},
];