mirror of
https://github.com/skidoodle/albert.lol.git
synced 2025-02-15 06:09:15 +01:00
🔥
This commit is contained in:
commit
abfc3e09b9
21 changed files with 553 additions and 0 deletions
6
.eslintrc.json
Normal file
6
.eslintrc.json
Normal file
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"extends": "next/core-web-vitals",
|
||||
"rules": {
|
||||
"@next/next/no-img-element": "off"
|
||||
}
|
||||
}
|
37
.gitignore
vendored
Normal file
37
.gitignore
vendored
Normal file
|
@ -0,0 +1,37 @@
|
|||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
||||
|
||||
# dependencies
|
||||
/node_modules
|
||||
/.pnp
|
||||
.pnp.js
|
||||
|
||||
# testing
|
||||
/coverage
|
||||
|
||||
# next.js
|
||||
/.next/
|
||||
/out/
|
||||
|
||||
# production
|
||||
/build
|
||||
|
||||
# misc
|
||||
.DS_Store
|
||||
*.pem
|
||||
|
||||
# debug
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
.pnpm-debug.log*
|
||||
|
||||
# local env files
|
||||
.env*.local
|
||||
|
||||
# vercel
|
||||
.vercel
|
||||
|
||||
# typescript
|
||||
*.tsbuildinfo
|
||||
|
||||
.vercel
|
5
next-env.d.ts
vendored
Normal file
5
next-env.d.ts
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
/// <reference types="next" />
|
||||
/// <reference types="next/image-types/global" />
|
||||
|
||||
// NOTE: This file should not be edited
|
||||
// see https://nextjs.org/docs/basic-features/typescript for more information.
|
13
next.config.js
Normal file
13
next.config.js
Normal file
|
@ -0,0 +1,13 @@
|
|||
const path = require('path')
|
||||
|
||||
module.exports = {
|
||||
productionBrowserSourceMaps: true,
|
||||
swcMinify: false,
|
||||
sassOptions: {
|
||||
includePaths: [path.join(__dirname, 'styles')]
|
||||
},
|
||||
images: {
|
||||
domains: ['i.albrt.hu', 'lastfm.freetls.fastly.net'],
|
||||
formats: ['image/avif', 'image/webp']
|
||||
}
|
||||
}
|
35
package.json
Normal file
35
package.json
Normal file
|
@ -0,0 +1,35 @@
|
|||
{
|
||||
"name": "portfolio",
|
||||
"version": "1.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "next dev",
|
||||
"build": "next build",
|
||||
"start": "next start",
|
||||
"lint": "next lint"
|
||||
},
|
||||
"dependencies": {
|
||||
"@fortawesome/fontawesome-svg-core": "^6.1.1",
|
||||
"@fortawesome/free-brands-svg-icons": "^6.1.1",
|
||||
"@fortawesome/free-solid-svg-icons": "^6.1.1",
|
||||
"@fortawesome/react-fontawesome": "^0.1.18",
|
||||
"@swc/core": "^1.2.160",
|
||||
"copy-to-clipboard": "^3.3.1",
|
||||
"next": "12.1.1",
|
||||
"react": "17.0.2",
|
||||
"react-dom": "17.0.2",
|
||||
"react-hot-toast": "^2.2.0",
|
||||
"goober": "2.1.8",
|
||||
"csstype": "^3.0.10",
|
||||
"sass": "^1.49.9",
|
||||
"use-last-fm": "^0.6.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "17.0.23",
|
||||
"@types/react": "17.0.43",
|
||||
"@types/react-dom": "17.0.14",
|
||||
"eslint": "8.12.0",
|
||||
"eslint-config-next": "12.1.1",
|
||||
"typescript": "4.6.3"
|
||||
}
|
||||
}
|
17
pages/_app.tsx
Normal file
17
pages/_app.tsx
Normal file
|
@ -0,0 +1,17 @@
|
|||
import { fas } from '@fortawesome/free-solid-svg-icons';
|
||||
import { fab } from '@fortawesome/free-brands-svg-icons';
|
||||
import { config, library } from '@fortawesome/fontawesome-svg-core';
|
||||
|
||||
import type { AppProps } from 'next/app'
|
||||
|
||||
import '../src/styles/globals.scss'
|
||||
import '@fortawesome/fontawesome-svg-core/styles.css'
|
||||
|
||||
library.add(fab, fas)
|
||||
config.autoAddCss = false
|
||||
|
||||
const MyApp = ({ Component, pageProps }: AppProps) => {
|
||||
return <Component {...pageProps} />
|
||||
}
|
||||
|
||||
export default MyApp
|
26
pages/_document.tsx
Normal file
26
pages/_document.tsx
Normal file
|
@ -0,0 +1,26 @@
|
|||
import { Html, Head, Main, NextScript } from 'next/document'
|
||||
|
||||
const Document = () => {
|
||||
return (
|
||||
<>
|
||||
<Html lang='en'>
|
||||
<Head>
|
||||
<link rel="preconnect" href="https://vitals.vercel-insights.com" />
|
||||
<link rel="preconnect" href="https://ws.audioscrobbler.com" />
|
||||
<meta property="og:url" content="https://albrt.hu" />
|
||||
<meta property="og:site_name" content="albrt.hu" />
|
||||
<meta name='title' content='albert' />
|
||||
<meta name='og:title' content='albert' />
|
||||
<meta name='description' content='system administrator' />
|
||||
<meta name='og:description' content='system administrator' />
|
||||
<meta name='theme-color' content='#000000' />
|
||||
<meta property='og:image' content='/favicon.ico' />
|
||||
</Head>
|
||||
<Main />
|
||||
<NextScript />
|
||||
</Html>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default Document
|
45
pages/index.tsx
Normal file
45
pages/index.tsx
Normal file
|
@ -0,0 +1,45 @@
|
|||
import { GetServerSideProps } from 'next'
|
||||
import Head from 'next/head'
|
||||
import Body from '../src/components/Body'
|
||||
import Footer from '../src/components/Footer'
|
||||
import Icon from '../src/components/Icon'
|
||||
import IconLayout from '../src/components/IconLayout'
|
||||
import MainLayout from '../src/components/MainLayout'
|
||||
import Spotify from '../src/components/Spotify'
|
||||
import Time from '../src/components/Time'
|
||||
import Weather from '../src/components/Weather'
|
||||
|
||||
const Home = ({data}: any) => {
|
||||
return(
|
||||
<>
|
||||
<Head>
|
||||
<title>albert</title>
|
||||
</Head>
|
||||
<Body>
|
||||
<MainLayout />
|
||||
<IconLayout>
|
||||
<Icon icon={['fab', 'discord']} reference={'albert#8838'} copy={true} />
|
||||
<Icon icon={['fab', 'steam']} reference={'https://steamcommunity.com/id/_albert'} copy={false} />
|
||||
<Icon icon={['fab', 'github']} reference={'https://github.com/skidoodle'} copy={false} />
|
||||
<Icon icon={['fa', 'envelope']} reference={'hello@albrt.hu'} copy={true} />
|
||||
<Icon icon={['fab', 'instagram']} reference={'https://instagram.com/albertadam_'} copy={false} />
|
||||
</IconLayout>
|
||||
<Time />
|
||||
<Weather data={data}/>
|
||||
<Spotify />
|
||||
</Body>
|
||||
<Footer />
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export const getServerSideProps: GetServerSideProps = async () => {
|
||||
const response = await fetch('https://api.openweathermap.org/data/2.5/weather?lat=47.51&lon=19.04&appid=1b3c10c18e894eaf1fd63eedde53fa54&units=metric')
|
||||
const data = await response.json()
|
||||
|
||||
return {
|
||||
props: { data }
|
||||
}
|
||||
}
|
||||
|
||||
export default Home
|
BIN
public/favicon.ico
Normal file
BIN
public/favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 25 KiB |
11
src/components/Body.tsx
Normal file
11
src/components/Body.tsx
Normal file
|
@ -0,0 +1,11 @@
|
|||
import styles from '../styles/Home.module.scss'
|
||||
|
||||
const Body = ({children}: {children: any}) => {
|
||||
return(
|
||||
<div className={styles.bodySection}>
|
||||
{children}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default Body
|
11
src/components/Footer.tsx
Normal file
11
src/components/Footer.tsx
Normal file
|
@ -0,0 +1,11 @@
|
|||
import styles from '../styles/Home.module.scss'
|
||||
|
||||
const Footer = () => {
|
||||
return(
|
||||
<div className={styles.footerLayout}>
|
||||
<a href='https://cigany.ninja' target="_blank" rel='noopener noreferrer'>?</a>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default Footer
|
36
src/components/Icon.tsx
Normal file
36
src/components/Icon.tsx
Normal file
|
@ -0,0 +1,36 @@
|
|||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||
import toast, { Toaster } from 'react-hot-toast';
|
||||
import copy from 'copy-to-clipboard'
|
||||
|
||||
const Icon = ({icon, reference, copy = false} : {icon: any, reference: any, copy?: boolean}) => {
|
||||
return(
|
||||
<>
|
||||
{
|
||||
copy ? (
|
||||
<a onClick={() => doThings(reference)}>
|
||||
<FontAwesomeIcon icon={icon} />
|
||||
</a>
|
||||
) : (
|
||||
<a href={reference} target='_blank' rel="noopener noreferrer" aria-label="Icon">
|
||||
<FontAwesomeIcon icon={icon} />
|
||||
</a>
|
||||
)
|
||||
}
|
||||
<Toaster position='bottom-left' reverseOrder={false} />
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
const doThings = (value: any) => {
|
||||
copy(value)
|
||||
toast.remove()
|
||||
toast.success('Successfully copied to clipboard', {
|
||||
style: {
|
||||
background: '#111',
|
||||
color: '#fff',
|
||||
fontSize: '1.1rem'
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export default Icon
|
13
src/components/IconLayout.tsx
Normal file
13
src/components/IconLayout.tsx
Normal file
|
@ -0,0 +1,13 @@
|
|||
import styles from '../styles/Home.module.scss'
|
||||
|
||||
const IconLayout = ({children}: {children: any}) => {
|
||||
return(
|
||||
<>
|
||||
<div className={styles.iconLayout}>
|
||||
{children}
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default IconLayout
|
14
src/components/MainLayout.tsx
Normal file
14
src/components/MainLayout.tsx
Normal file
|
@ -0,0 +1,14 @@
|
|||
import styles from '../styles/Home.module.scss'
|
||||
|
||||
const MainLayout = () => {
|
||||
return(
|
||||
<>
|
||||
<div className={styles.mainLayout}>
|
||||
<h1>albert</h1>
|
||||
<p>17-year-old <b>system administrator</b> and student from Hungary</p>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default MainLayout
|
31
src/components/Spotify.tsx
Normal file
31
src/components/Spotify.tsx
Normal file
|
@ -0,0 +1,31 @@
|
|||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||
import { useLastFM } from 'use-last-fm'
|
||||
import styles from '../styles/Home.module.scss'
|
||||
|
||||
const Spotify = () => {
|
||||
const lastFM = useLastFM('albrtadam', 'f6d19bc25ca340225c70c3d386cd4eab');
|
||||
|
||||
return(
|
||||
<div className={styles.spotify}>
|
||||
{lastFM.status === 'playing'
|
||||
?
|
||||
<>
|
||||
<a href={lastFM.song.url} target='_blank' rel="noopener noreferrer">
|
||||
<img src={lastFM.song.art} width={50} height={50} className={styles.song} alt=""/>
|
||||
<p>Listening to <b>{lastFM.song.name}</b></p>
|
||||
</a>
|
||||
</>
|
||||
:
|
||||
<>
|
||||
<img src="https://i.albrt.hu/66e8e4c6.webp" width={50} height={50} className={styles.nosong} alt=""/>
|
||||
<p>Not listening to anything</p>
|
||||
</>
|
||||
}
|
||||
<div className={styles.tinyText}>
|
||||
<FontAwesomeIcon icon={['fab', 'spotify']} /> Spotify
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default Spotify
|
23
src/components/Time.tsx
Normal file
23
src/components/Time.tsx
Normal file
|
@ -0,0 +1,23 @@
|
|||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||
import { useEffect, useState } from 'react'
|
||||
|
||||
import styles from '../styles/Home.module.scss'
|
||||
|
||||
const Timer = () => {
|
||||
const [date, setDate] = useState(new Date())
|
||||
|
||||
useEffect(() => {
|
||||
const interval = setInterval(() => {
|
||||
setDate(new Date())
|
||||
}, 1000)
|
||||
return () => clearInterval(interval)
|
||||
})
|
||||
|
||||
return(
|
||||
<div className={styles.time}>
|
||||
<p><FontAwesomeIcon icon={['fas', 'clock']} /> {date.toLocaleDateString('en-GB', { dateStyle: 'short' }) + ' • ' + date.toLocaleTimeString('en-GB', { timeStyle: 'medium', hour12: true}).toUpperCase()}</p>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default Timer
|
27
src/components/Weather.tsx
Normal file
27
src/components/Weather.tsx
Normal file
|
@ -0,0 +1,27 @@
|
|||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||
import styles from '../styles/Home.module.scss'
|
||||
|
||||
const Weather = ({data}: {data: any}) => {
|
||||
const { temp: temperature } = data.main
|
||||
const { icon: weatherIcon, description: weatherDescription} = data.weather[0]
|
||||
|
||||
const icons: any = {
|
||||
_01d: ['fas', 'sun'], _01n: ['fas', 'moon'],
|
||||
_02d: ['fas', 'cloud-sun'], _02n: ['fas', 'cloud-moon'],
|
||||
_03d: ['fas', 'cloud'], _03n: ['fas', 'cloud'],
|
||||
_04d: ['fas', 'clouds'], _04n: ['fas', 'clouds'],
|
||||
_09d: ['fas', 'cloud-drizzle'], _09n: ['fas', 'cloud-drizzle'],
|
||||
_10d: ['fas', 'cloud-showers-heavy'], _10n: ['fas', 'cloud-showers-heavy'],
|
||||
_11d: ['fas', 'cloud-bolt-sun'], _11n: ['fas', 'cloud-bolt-moon'],
|
||||
_13d: ['fas', 'snow-flake'], _13n: ['fas', 'snow-flake'],
|
||||
_50d: ['fas', 'cloud-fog'], _50n: ['fas', 'cloud-fog']
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={styles.weather}>
|
||||
<FontAwesomeIcon icon={icons[`_${weatherIcon}`]}/> <p>It's currently <b>{parseInt(temperature)} °C</b> <span>({weatherDescription})</span> in <a href='https://weather.com/en-GB/weather/today/l/b979f874d2f515646f37e2bb434a85cc04869c5a35c6bdf1c6fba26f659313f0' target="_blank" rel='noopener noreferrer'><b>Budapest</b></a></p>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default Weather
|
151
src/styles/Home.module.scss
Normal file
151
src/styles/Home.module.scss
Normal file
|
@ -0,0 +1,151 @@
|
|||
@import '_variables';
|
||||
|
||||
.bodySection {
|
||||
margin-top: 8rem;
|
||||
margin-left: 10%;
|
||||
margin-right: 10%;
|
||||
animation: fadeIn .4s forwards;
|
||||
transition: all .2s ease-in-out;
|
||||
}
|
||||
|
||||
.mainLayout {
|
||||
h1 {
|
||||
line-height: .2;
|
||||
font-size: 3rem;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
p {
|
||||
color: $secondary-color;
|
||||
font-size: 1rem;
|
||||
font-weight: 400;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.iconLayout {
|
||||
margin-bottom: 5%;
|
||||
|
||||
svg {
|
||||
font-size: 1.2em;
|
||||
cursor: pointer;
|
||||
margin-right: 7%;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
}
|
||||
|
||||
.time,
|
||||
.weather,
|
||||
.spotify {
|
||||
animation: fadeIn .6s forwards;
|
||||
opacity: 0;
|
||||
font-size: 1em;
|
||||
}
|
||||
.time svg,
|
||||
.weather svg {
|
||||
font-size: .9rem;
|
||||
}
|
||||
|
||||
.time {
|
||||
animation-delay: 0.2s;
|
||||
}
|
||||
|
||||
.weather {
|
||||
opacity: 0;
|
||||
animation-delay: 0.5s;
|
||||
|
||||
img {
|
||||
float: left;
|
||||
}
|
||||
|
||||
p {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
a {
|
||||
font-size: 1em;
|
||||
}
|
||||
a:hover {
|
||||
text-decoration: none;
|
||||
color: #C7D2FE;
|
||||
}
|
||||
}
|
||||
|
||||
.spotify {
|
||||
font-size: .9em;
|
||||
margin-top: 5%;
|
||||
opacity: 0;
|
||||
animation-delay: .7s;
|
||||
padding: 1rem 1rem 1.8rem 1rem;
|
||||
border: 1px solid $spotify-box-color;
|
||||
border-radius: .5rem;
|
||||
cursor: pointer;
|
||||
|
||||
img {
|
||||
border-radius: 10px;
|
||||
float: left;
|
||||
margin-right: 5%;
|
||||
}
|
||||
|
||||
p {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
.tinyText {
|
||||
font-weight: 300;
|
||||
font-size: .8em;
|
||||
|
||||
svg {
|
||||
margin-top: 5px;
|
||||
color: #1DB954;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.footerLayout {
|
||||
position: absolute;
|
||||
bottom: 1rem;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
|
||||
a {
|
||||
cursor: pointer;
|
||||
text-decoration: none;
|
||||
|
||||
&:hover {
|
||||
color: #C7D2FE
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media(min-width: 1200px) {
|
||||
.bodySection {
|
||||
margin-left: 30%;
|
||||
margin-right: 45%;
|
||||
}
|
||||
|
||||
.iconLayout {
|
||||
margin-bottom: 2%;
|
||||
}
|
||||
|
||||
.spotify {
|
||||
margin-top: 8%;
|
||||
width: 80%;
|
||||
}
|
||||
}
|
||||
|
||||
@media(min-height: 800px) {
|
||||
.bodySection {
|
||||
margin-top: 15rem;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fadeIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
6
src/styles/_variables.scss
Normal file
6
src/styles/_variables.scss
Normal file
|
@ -0,0 +1,6 @@
|
|||
$background-color: #000000;
|
||||
$primary-color: #ffffff;
|
||||
$secondary-color: #9CA3AF;
|
||||
$selection-color: #8039e2;
|
||||
$spotify-box-color: #521c9e;
|
||||
$font: 'Inter', sans-serif;
|
26
src/styles/globals.scss
Normal file
26
src/styles/globals.scss
Normal file
|
@ -0,0 +1,26 @@
|
|||
@import '_variables';
|
||||
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@200;400;700&display=swap');
|
||||
|
||||
html,
|
||||
body {
|
||||
background-color: $background-color;
|
||||
color: $primary-color;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
font-family: $font;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
::selection {
|
||||
background: rgba($selection-color, .7);
|
||||
color: $primary-color;
|
||||
}
|
||||
|
||||
a {
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
20
tsconfig.json
Normal file
20
tsconfig.json
Normal file
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"target": "es5",
|
||||
"lib": ["dom", "dom.iterable", "esnext"],
|
||||
"allowJs": true,
|
||||
"skipLibCheck": true,
|
||||
"strict": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"noEmit": true,
|
||||
"esModuleInterop": true,
|
||||
"module": "esnext",
|
||||
"moduleResolution": "node",
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"jsx": "preserve",
|
||||
"incremental": true
|
||||
},
|
||||
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
|
||||
"exclude": ["node_modules"]
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue