run prettier formatting on all files

This commit is contained in:
Amruth Pillai
2023-07-13 08:54:37 +02:00
parent 984078db76
commit 161ca0ee28
37 changed files with 166 additions and 1047 deletions

2
.github/FUNDING.yml vendored
View File

@ -1,2 +1,2 @@
github: AmruthPillai github: AmruthPillai
custom: https://paypal.me/RajaRajanA custom: https://paypal.me/amruthde

View File

@ -1,9 +1,9 @@
name: 🐞 Bug Report name: 🐞 Bug Report
description: Create a bug report to help improve Reactive Resume. description: Create a bug report to help improve Reactive Resume.
title: "[Bug] <title>" title: '[Bug] <title>'
labels: [Bug, Needs Triage] labels: [Bug, Needs Triage]
assignees: "AmruthPillai" assignees: 'AmruthPillai'
body: body:
- type: checkboxes - type: checkboxes

View File

@ -1,9 +1,9 @@
name: ✨ Feature Request name: ✨ Feature Request
description: Suggest an feature or idea that you would like to see in Reactive Resume. description: Suggest an feature or idea that you would like to see in Reactive Resume.
title: "[Feature] <title>" title: '[Feature] <title>'
labels: [Feature, Needs Triage] labels: [Feature, Needs Triage]
assignees: "AmruthPillai" assignees: 'AmruthPillai'
body: body:
- type: checkboxes - type: checkboxes

View File

@ -0,0 +1,50 @@
import Tilt from 'react-parallax-tilt';
import { defaultTiltProps } from '@/constants/tilt';
import HomeActions from '../Actions';
import HeroBackground from '../Background';
import HeroPattern from '../Pattern';
const HeroSection = () => (
<section className="relative">
<HeroPattern />
<HeroBackground />
<div className="mx-auto max-w-7xl px-6 pb-24 pt-10 sm:pb-32 lg:flex lg:px-8 lg:py-52">
<div className="mx-auto max-w-2xl shrink-0 lg:mx-0 lg:max-w-xl lg:pt-12">
<div className="mt-10 space-y-2">
<h6 className="text-base font-bold tracking-wide">Finally,</h6>
<h1 className="text-4xl font-bold !leading-[1.15] tracking-tight sm:text-6xl">
A free and open-source resume builder
</h1>
</div>
<p className="prose prose-base prose-zinc mt-6 text-lg leading-8 dark:prose-invert">
Reactive Resume is a free and open-source resume builder that simplifies the tasks of creating, updating, and
sharing your resume.
</p>
<div className="mt-12 space-x-4">
<HomeActions />
</div>
</div>
<div className="mx-auto mt-16 flex max-w-2xl sm:mt-24 lg:ml-10 lg:mr-0 lg:mt-0 lg:max-w-none lg:flex-none xl:ml-32">
<div className="max-w-3xl flex-none sm:max-w-5xl lg:max-w-none">
<Tilt {...defaultTiltProps}>
<img
width={2432}
height={1442}
src="/images/screenshots/builder.png"
alt="Reactive Resume Screenshot - Builder Screen"
className="w-[76rem] rounded-lg bg-zinc-50/5 shadow-2xl ring-1 ring-zinc-950/10 dark:bg-zinc-950/5 dark:ring-zinc-50/10"
/>
</Tilt>
</div>
</div>
</div>
</section>
);
export default HeroSection;

View File

@ -1,5 +1,5 @@
.content { .content {
@apply rounded px-6 text-sm shadow lg:w-1/2 xl:w-2/5; @apply rounded px-6 text-sm shadow lg:w-2/3 xl:w-1/2;
@apply absolute inset-4 sm:inset-x-4 sm:inset-y-auto lg:inset-auto; @apply absolute inset-4 sm:inset-x-4 sm:inset-y-auto lg:inset-auto;
@apply overflow-scroll bg-zinc-100 dark:bg-zinc-900 lg:overflow-auto; @apply overflow-scroll bg-zinc-100 dark:bg-zinc-900 lg:overflow-auto;
@apply max-h-[90vh] min-h-fit; @apply max-h-[90vh] min-h-fit;

View File

@ -8,7 +8,7 @@ export const Copyright = ({ className }: Props) => (
<div <div
className={clsx('prose prose-sm prose-zinc flex flex-col gap-y-1 text-xs opacity-40 dark:prose-invert', className)} className={clsx('prose prose-sm prose-zinc flex flex-col gap-y-1 text-xs opacity-40 dark:prose-invert', className)}
> >
<span className="font-medium">v4.0.0</span> <span className="font-medium">v{process.env.appVersion}</span>
<span> <span>
Licensed under <a href="https://github.com/AmruthPillai/Reactive-Resume/blob/main/LICENSE">MIT</a> Licensed under <a href="https://github.com/AmruthPillai/Reactive-Resume/blob/main/LICENSE">MIT</a>
</span> </span>

View File

@ -13,7 +13,7 @@ const ThemeSwitch = styled(Switch)(({ theme }) => ({
transform: 'translateX(22px)', transform: 'translateX(22px)',
'& .MuiSwitch-thumb:before': { '& .MuiSwitch-thumb:before': {
backgroundImage: `url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 20 20"><path fill="${encodeURIComponent( backgroundImage: `url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 20 20"><path fill="${encodeURIComponent(
'#fff' '#fff',
)}" d="M4.2 2.5l-.7 1.8-1.8.7 1.8.7.7 1.8.6-1.8L6.7 5l-1.9-.7-.6-1.8zm15 8.3a6.7 6.7 0 11-6.6-6.6 5.8 5.8 0 006.6 6.6z"/></svg>')`, )}" d="M4.2 2.5l-.7 1.8-1.8.7 1.8.7.7 1.8.6-1.8L6.7 5l-1.9-.7-.6-1.8zm15 8.3a6.7 6.7 0 11-6.6-6.6 5.8 5.8 0 006.6 6.6z"/></svg>')`,
}, },
'& + .MuiSwitch-track': { '& + .MuiSwitch-track': {
@ -36,7 +36,7 @@ const ThemeSwitch = styled(Switch)(({ theme }) => ({
backgroundRepeat: 'no-repeat', backgroundRepeat: 'no-repeat',
backgroundPosition: 'center', backgroundPosition: 'center',
backgroundImage: `url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 20 20"><path fill="${encodeURIComponent( backgroundImage: `url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 20 20"><path fill="${encodeURIComponent(
'#fff' '#fff',
)}" d="M9.305 1.667V3.75h1.389V1.667h-1.39zm-4.707 1.95l-.982.982L5.09 6.072l.982-.982-1.473-1.473zm10.802 0L13.927 5.09l.982.982 1.473-1.473-.982-.982zM10 5.139a4.872 4.872 0 00-4.862 4.86A4.872 4.872 0 0010 14.862 4.872 4.872 0 0014.86 10 4.872 4.872 0 0010 5.139zm0 1.389A3.462 3.462 0 0113.471 10a3.462 3.462 0 01-3.473 3.472A3.462 3.462 0 016.527 10 3.462 3.462 0 0110 6.528zM1.665 9.305v1.39h2.083v-1.39H1.666zm14.583 0v1.39h2.084v-1.39h-2.084zM5.09 13.928L3.616 15.4l.982.982 1.473-1.473-.982-.982zm9.82 0l-.982.982 1.473 1.473.982-.982-1.473-1.473zM9.305 16.25v2.083h1.389V16.25h-1.39z"/></svg>')`, )}" d="M9.305 1.667V3.75h1.389V1.667h-1.39zm-4.707 1.95l-.982.982L5.09 6.072l.982-.982-1.473-1.473zm10.802 0L13.927 5.09l.982.982 1.473-1.473-.982-.982zM10 5.139a4.872 4.872 0 00-4.862 4.86A4.872 4.872 0 0010 14.862 4.872 4.872 0 0014.86 10 4.872 4.872 0 0010 5.139zm0 1.389A3.462 3.462 0 0113.471 10a3.462 3.462 0 01-3.473 3.472A3.462 3.462 0 016.527 10 3.462 3.462 0 0110 6.528zM1.665 9.305v1.39h2.083v-1.39H1.666zm14.583 0v1.39h2.084v-1.39h-2.084zM5.09 13.928L3.616 15.4l.982.982 1.473-1.473-.982-.982zm9.82 0l-.982.982 1.473 1.473.982-.982-1.473-1.473zM9.305 16.25v2.083h1.389V16.25h-1.39z"/></svg>')`,
}, },
}, },

View File

@ -54,5 +54,5 @@ export const languageMap: Record<string, Language> = languages.reduce(
...acc, ...acc,
[lang.code]: lang, [lang.code]: lang,
}), }),
{} {},
); );

View File

@ -10,7 +10,7 @@ export const FILENAME_TIMESTAMP = 'DDMMYYYYHHmmss';
// Links // Links
export const DOCS_URL = 'https://docs.rxresu.me'; export const DOCS_URL = 'https://docs.rxresu.me';
export const DONATION_URL = 'https://paypal.me/RajaRajanA'; export const DONATION_URL = 'https://paypal.me/amruthde';
export const TRANSLATE_URL = 'https://translate.rxresu.me/'; export const TRANSLATE_URL = 'https://translate.rxresu.me/';
export const DIGITALOCEAN_URL = 'https://pillai.xyz/digitalocean'; export const DIGITALOCEAN_URL = 'https://pillai.xyz/digitalocean';
export const REDDIT_URL = 'https://www.reddit.com/r/reactiveresume/'; export const REDDIT_URL = 'https://www.reddit.com/r/reactiveresume/';

View File

@ -121,7 +121,7 @@ const LoginModal: React.FC = () => {
> >
<p>{t('modals.auth.login.body')}</p> <p>{t('modals.auth.login.body')}</p>
<form className="grid gap-4 xl:w-2/3"> <form className="grid gap-4">
<Controller <Controller
name="identifier" name="identifier"
control={control} control={control}

View File

@ -62,7 +62,7 @@
"webfontloader": "^1.6.28" "webfontloader": "^1.6.28"
}, },
"devDependencies": { "devDependencies": {
"@babel/core": "^7.22.8", "@babel/core": "^7.22.9",
"@fontsource/ibm-plex-sans": "^5.0.5", "@fontsource/ibm-plex-sans": "^5.0.5",
"@tailwindcss/forms": "^0.5.3", "@tailwindcss/forms": "^0.5.3",
"@tailwindcss/typography": "^0.5.9", "@tailwindcss/typography": "^0.5.9",
@ -70,7 +70,7 @@
"@types/lodash": "^4.14.195", "@types/lodash": "^4.14.195",
"@types/node": "^20.4.1", "@types/node": "^20.4.1",
"@types/react": "^18.2.14", "@types/react": "^18.2.14",
"@types/react-dom": "^18.2.6", "@types/react-dom": "^18.2.7",
"@types/react-redux": "^7.1.25", "@types/react-redux": "^7.1.25",
"@types/uuid": "^9.0.2", "@types/uuid": "^9.0.2",
"@types/webfontloader": "^1.6.35", "@types/webfontloader": "^1.6.35",

View File

@ -1,14 +1,11 @@
import type { GetStaticProps, NextPage } from 'next'; import type { GetStaticProps, NextPage } from 'next';
import { serverSideTranslations } from 'next-i18next/serverSideTranslations'; import { serverSideTranslations } from 'next-i18next/serverSideTranslations';
import Tilt from 'react-parallax-tilt';
import HeroBackground from '@/components/home/Background';
import Footer from '@/components/home/Footer'; import Footer from '@/components/home/Footer';
import Header from '@/components/home/Header'; import Header from '@/components/home/Header';
import HeroPattern from '@/components/home/Pattern'; import HeroSection from '@/components/home/sections/Hero';
import LogoSection from '@/components/home/sections/Logo'; import LogoSection from '@/components/home/sections/Logo';
import StatsSection from '@/components/home/sections/Stats'; import StatsSection from '@/components/home/sections/Stats';
import { defaultTiltProps } from '@/constants/tilt';
export const getStaticProps: GetStaticProps = async ({ locale = 'en' }) => ({ export const getStaticProps: GetStaticProps = async ({ locale = 'en' }) => ({
props: { props: {
@ -21,43 +18,13 @@ const Home: NextPage = () => (
<Header /> <Header />
<main className="relative isolate mb-[450px] overflow-hidden bg-zinc-50 dark:bg-zinc-950"> <main className="relative isolate mb-[450px] overflow-hidden bg-zinc-50 dark:bg-zinc-950">
<section className="relative"> {/* Hero */}
<HeroPattern /> <HeroSection />
<HeroBackground />
<div className="mx-auto max-w-7xl px-6 pb-24 pt-10 sm:pb-32 lg:flex lg:px-8 lg:py-52">
<div className="mx-auto max-w-2xl shrink-0 lg:mx-0 lg:max-w-xl lg:pt-12">
<div className="mt-10 space-y-2">
<h6 className="text-base font-bold tracking-wide">Finally,</h6>
<h1 className="text-4xl font-bold !leading-[1.15] tracking-tight sm:text-6xl">
A free and open-source resume builder
</h1>
</div>
<p className="prose prose-base prose-zinc mt-6 text-lg leading-8 dark:prose-invert">
Reactive Resume is a free and open-source resume builder that simplifies the tasks of creating, updating,
and sharing your resume.
</p>
</div>
<div className="mx-auto mt-16 flex max-w-2xl sm:mt-24 lg:ml-10 lg:mr-0 lg:mt-0 lg:max-w-none lg:flex-none xl:ml-32">
<div className="max-w-3xl flex-none sm:max-w-5xl lg:max-w-none">
<Tilt {...defaultTiltProps}>
<img
width={2432}
height={1442}
src="/images/screenshots/builder.png"
alt="Reactive Resume Screenshot - Builder Screen"
className="w-[76rem] rounded-lg bg-zinc-50/5 shadow-2xl ring-1 ring-zinc-950/10 dark:bg-zinc-950/5 dark:ring-zinc-50/10"
/>
</Tilt>
</div>
</div>
</div>
</section>
{/* Logo Cloud */}
<LogoSection /> <LogoSection />
{/* Statistics */}
<StatsSection /> <StatsSection />
</main> </main>

View File

@ -83,7 +83,7 @@ export const resetPassword = async (resetPasswordParams: ResetPasswordParams) =>
export const updateProfile = async (updateProfileParams: UpdateProfileParams) => { export const updateProfile = async (updateProfileParams: UpdateProfileParams) => {
const { data: user } = await axios.patch<User, AxiosResponse<User>, UpdateProfileParams>( const { data: user } = await axios.patch<User, AxiosResponse<User>, UpdateProfileParams>(
'/auth/update-profile', '/auth/update-profile',
updateProfileParams updateProfileParams,
); );
store.dispatch(setUser(user)); store.dispatch(setUser(user));

View File

@ -46,7 +46,7 @@ axios.interceptors.response.use(
} }
throw error; throw error;
} },
); );
export default axios; export default axios;

View File

@ -9,6 +9,6 @@ export type PrintResumeAsPdfParams = {
export const printResumeAsPdf = (printResumeAsPdfParams: PrintResumeAsPdfParams): Promise<string> => export const printResumeAsPdf = (printResumeAsPdfParams: PrintResumeAsPdfParams): Promise<string> =>
axios axios
.get( .get(
`/printer/${printResumeAsPdfParams.username}/${printResumeAsPdfParams.slug}?lastUpdated=${printResumeAsPdfParams.lastUpdated}` `/printer/${printResumeAsPdfParams.username}/${printResumeAsPdfParams.slug}?lastUpdated=${printResumeAsPdfParams.lastUpdated}`,
) )
.then((res) => res.data); .then((res) => res.data);

View File

@ -20,7 +20,7 @@ const DEBOUNCE_WAIT = 1000;
const debouncedSync = debounce( const debouncedSync = debounce(
(resume: Resume, dispatch: AppDispatch) => updateResume(resume).then((resume) => dispatch(setResume(resume))), (resume: Resume, dispatch: AppDispatch) => updateResume(resume).then((resume) => dispatch(setResume(resume))),
DEBOUNCE_WAIT DEBOUNCE_WAIT,
); );
function* handleSync(dispatch: AppDispatch) { function* handleSync(dispatch: AppDispatch) {
@ -31,7 +31,7 @@ function* handleSync(dispatch: AppDispatch) {
function* syncSaga(dispatch: AppDispatch) { function* syncSaga(dispatch: AppDispatch) {
yield takeLatest([setResumeState, addItem, editItem, duplicateItem, deleteItem, addSection, deleteSection], () => yield takeLatest([setResumeState, addItem, editItem, duplicateItem, deleteItem, addSection, deleteSection], () =>
handleSync(dispatch) handleSync(dispatch),
); );
} }

View File

@ -17,7 +17,7 @@ import { addHttp, formatLocation, getPhotoClassNames } from '@/utils/template';
export const MastheadSidebar: React.FC = () => { export const MastheadSidebar: React.FC = () => {
const dateFormat: string = useAppSelector((state) => get(state.resume.present, 'metadata.date.format')); const dateFormat: string = useAppSelector((state) => get(state.resume.present, 'metadata.date.format'));
const { name, headline, photo, email, phone, birthdate, website, location, profiles } = useAppSelector( const { name, headline, photo, email, phone, birthdate, website, location, profiles } = useAppSelector(
(state) => state.resume.present.basics (state) => state.resume.present.basics,
); );
const theme: ThemeConfig = useAppSelector((state) => get(state.resume.present, 'metadata.theme', {} as ThemeConfig)); const theme: ThemeConfig = useAppSelector((state) => get(state.resume.present, 'metadata.theme', {} as ThemeConfig));
const contrast = useMemo(() => getContrastColor(theme.primary), [theme.primary]); const contrast = useMemo(() => getContrastColor(theme.primary), [theme.primary]);

View File

@ -18,7 +18,7 @@ import { addHttp, formatLocation, getPhotoClassNames } from '@/utils/template';
export const MastheadSidebar: React.FC = () => { export const MastheadSidebar: React.FC = () => {
const dateFormat: string = useAppSelector((state) => get(state.resume.present, 'metadata.date.format')); const dateFormat: string = useAppSelector((state) => get(state.resume.present, 'metadata.date.format'));
const { name, headline, photo, email, phone, birthdate, website, location, profiles } = useAppSelector( const { name, headline, photo, email, phone, birthdate, website, location, profiles } = useAppSelector(
(state) => state.resume.present.basics (state) => state.resume.present.basics,
); );
const theme: ThemeConfig = useAppSelector((state) => get(state.resume.present, 'metadata.theme', {} as ThemeConfig)); const theme: ThemeConfig = useAppSelector((state) => get(state.resume.present, 'metadata.theme', {} as ThemeConfig));
const contrast = useMemo(() => getContrastColor(theme.primary), [theme.primary]); const contrast = useMemo(() => getContrastColor(theme.primary), [theme.primary]);

View File

@ -13,7 +13,7 @@ export const MastheadSidebar: React.FC = () => {
const dateFormat: string = useAppSelector((state) => get(state.resume.present, 'metadata.date.format')); const dateFormat: string = useAppSelector((state) => get(state.resume.present, 'metadata.date.format'));
const primaryColor: string = useAppSelector((state) => get(state.resume.present, 'metadata.theme.primary')); const primaryColor: string = useAppSelector((state) => get(state.resume.present, 'metadata.theme.primary'));
const { name, headline, photo, email, phone, birthdate, website, location, profiles } = useAppSelector( const { name, headline, photo, email, phone, birthdate, website, location, profiles } = useAppSelector(
(state) => state.resume.present.basics (state) => state.resume.present.basics,
); );
return ( return (

View File

@ -12,7 +12,7 @@ import { addHttp, formatLocation, getPhotoClassNames } from '@/utils/template';
const Masthead = () => { const Masthead = () => {
const dateFormat: string = useAppSelector((state) => get(state.resume.present, 'metadata.date.format')); const dateFormat: string = useAppSelector((state) => get(state.resume.present, 'metadata.date.format'));
const { name, photo, email, phone, website, birthdate, headline, location, profiles } = useAppSelector( const { name, photo, email, phone, website, birthdate, headline, location, profiles } = useAppSelector(
(state) => state.resume.present.basics (state) => state.resume.present.basics,
); );
return ( return (

View File

@ -14,7 +14,7 @@ import { addHttp, formatLocation, getPhotoClassNames } from '@/utils/template';
const Masthead: React.FC = () => { const Masthead: React.FC = () => {
const dateFormat: string = useAppSelector((state) => get(state.resume.present, 'metadata.date.format')); const dateFormat: string = useAppSelector((state) => get(state.resume.present, 'metadata.date.format'));
const { name, photo, headline, summary, email, phone, birthdate, website, location, profiles } = useAppSelector( const { name, photo, headline, summary, email, phone, birthdate, website, location, profiles } = useAppSelector(
(state) => state.resume.present.basics (state) => state.resume.present.basics,
); );
const theme: ThemeConfig = useAppSelector((state) => get(state.resume.present, 'metadata.theme', {} as ThemeConfig)); const theme: ThemeConfig = useAppSelector((state) => get(state.resume.present, 'metadata.theme', {} as ThemeConfig));

View File

@ -11,7 +11,7 @@ import { addHttp, formatLocation, getPhotoClassNames } from '@/utils/template';
const Masthead: React.FC = () => { const Masthead: React.FC = () => {
const dateFormat: string = useAppSelector((state) => get(state.resume.present, 'metadata.date.format')); const dateFormat: string = useAppSelector((state) => get(state.resume.present, 'metadata.date.format'));
const { name, photo, email, phone, website, birthdate, headline, location, profiles } = useAppSelector( const { name, photo, email, phone, website, birthdate, headline, location, profiles } = useAppSelector(
(state) => state.resume.present.basics (state) => state.resume.present.basics,
); );
return ( return (

View File

@ -1,5 +1,5 @@
import { ThemeConfig } from 'schema';
import get from 'lodash/get'; import get from 'lodash/get';
import { ThemeConfig } from 'schema';
import { useAppSelector } from '@/store/hooks'; import { useAppSelector } from '@/store/hooks';

View File

@ -1,9 +1,9 @@
import { Cake, Email, Phone, Public, Room } from '@mui/icons-material'; import { Cake, Email, Phone, Public, Room } from '@mui/icons-material';
import { ThemeConfig } from 'schema';
import clsx from 'clsx'; import clsx from 'clsx';
import get from 'lodash/get'; import get from 'lodash/get';
import isEmpty from 'lodash/isEmpty'; import isEmpty from 'lodash/isEmpty';
import { useMemo } from 'react'; import { useMemo } from 'react';
import { ThemeConfig } from 'schema';
import Markdown from '@/components/shared/Markdown'; import Markdown from '@/components/shared/Markdown';
import { useAppSelector } from '@/store/hooks'; import { useAppSelector } from '@/store/hooks';
@ -16,7 +16,7 @@ import { addHttp, formatLocation, getPhotoClassNames } from '@/utils/template';
export const MastheadSidebar: React.FC = () => { export const MastheadSidebar: React.FC = () => {
const dateFormat: string = useAppSelector((state) => get(state.resume.present, 'metadata.date.format')); const dateFormat: string = useAppSelector((state) => get(state.resume.present, 'metadata.date.format'));
const { name, photo, email, phone, birthdate, website, location, profiles } = useAppSelector( const { name, photo, email, phone, birthdate, website, location, profiles } = useAppSelector(
(state) => state.resume.present.basics (state) => state.resume.present.basics,
); );
return ( return (

View File

@ -1,8 +1,8 @@
import { ListItem, Location, PhotoFilters } from 'schema';
import clsx from 'clsx'; import clsx from 'clsx';
import get from 'lodash/get'; import get from 'lodash/get';
import isArray from 'lodash/isArray'; import isArray from 'lodash/isArray';
import isEmpty from 'lodash/isEmpty'; import isEmpty from 'lodash/isEmpty';
import { ListItem, Location, PhotoFilters } from 'schema';
export type Required<T, K extends keyof T> = T & { [P in K]-?: T[P] }; export type Required<T, K extends keyof T> = T & { [P in K]-?: T[P] };
@ -55,7 +55,7 @@ export const parseListItemPath = (item: ListItem, path: string | string[], separ
export const getPhotoClassNames = (filters: PhotoFilters) => export const getPhotoClassNames = (filters: PhotoFilters) =>
clsx({ clsx({
'object-cover': true, 'object-cover aspect-square': true,
grayscale: filters.grayscale, grayscale: filters.grayscale,
'!border-[4px] !border-solid': filters.border, '!border-[4px] !border-solid': filters.border,
'rounded-lg': filters.shape === 'rounded-square', 'rounded-lg': filters.shape === 'rounded-square',

View File

@ -11,7 +11,7 @@ const FontWrapper: React.FC<React.PropsWithChildren<unknown>> = ({ children }) =
const WebFont = (await import('webfontloader')).default; const WebFont = (await import('webfontloader')).default;
const families = Object.values(typography.family).reduce( const families = Object.values(typography.family).reduce(
(acc, family) => [...acc, `${family}:400,600,700`], (acc, family) => [...acc, `${family}:400,600,700`],
[] as string[] [] as string[],
); );
WebFont.load({ google: { families } }); WebFont.load({ google: { families } });

View File

@ -3,9 +3,9 @@
"version": "3.8.1", "version": "3.8.1",
"private": true, "private": true,
"scripts": { "scripts": {
"dev": "env-cmd --silent cross-var cross-env VERSION=$npm_package_version turbo run dev", "dev": "dotenv -- turbo run dev",
"build": "env-cmd --silent cross-var cross-env VERSION=$npm_package_version turbo run build", "build": "dotenv -- turbo run build",
"start": "env-cmd --silent cross-var cross-env VERSION=$npm_package_version turbo run start", "start": "dotenv -- turbo run start",
"format": "prettier --write --loglevel silent --cache .", "format": "prettier --write --loglevel silent --cache .",
"lint": "turbo run lint", "lint": "turbo run lint",
"update-dependencies": "ncu -x nanoid --deep -u && pnpm install", "update-dependencies": "ncu -x nanoid --deep -u && pnpm install",
@ -17,10 +17,7 @@
"server" "server"
], ],
"dependencies": { "dependencies": {
"cross-env": "^7.0.3", "dotenv-cli": "^7.2.1"
"cross-var": "^1.1.0",
"env-cmd": "^10.1.0",
"uuid": "^9.0.0"
}, },
"devDependencies": { "devDependencies": {
"@types/node": "^20.4.1", "@types/node": "^20.4.1",

1006
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,4 @@
<!DOCTYPE html> <!doctype html>
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="UTF-8" /> <meta charset="UTF-8" />

View File

@ -20,7 +20,7 @@ export class AuthService {
private schedulerRegistry: SchedulerRegistry, private schedulerRegistry: SchedulerRegistry,
private configService: ConfigService, private configService: ConfigService,
private usersService: UsersService, private usersService: UsersService,
private jwtService: JwtService private jwtService: JwtService,
) {} ) {}
async register(registerDto: RegisterDto) { async register(registerDto: RegisterDto) {
@ -49,7 +49,7 @@ export class AuthService {
if (!isPasswordMatching) { if (!isPasswordMatching) {
throw new HttpException( throw new HttpException(
'The username/email and password combination provided was incorrect.', 'The username/email and password combination provided was incorrect.',
HttpStatus.UNAUTHORIZED HttpStatus.UNAUTHORIZED,
); );
} }
} }
@ -64,7 +64,7 @@ export class AuthService {
} catch (error) { } catch (error) {
throw new HttpException( throw new HttpException(
'The username/email and password combination provided was incorrect.', 'The username/email and password combination provided was incorrect.',
HttpStatus.UNAUTHORIZED HttpStatus.UNAUTHORIZED,
); );
} }
} }

View File

@ -8,7 +8,10 @@ import { UsersService } from '@/users/users.service';
@Injectable() @Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) { export class JwtStrategy extends PassportStrategy(Strategy) {
constructor(configService: ConfigService, private readonly usersService: UsersService) { constructor(
configService: ConfigService,
private readonly usersService: UsersService,
) {
super({ super({
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(), jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
secretOrKey: configService.get('auth.jwtSecret'), secretOrKey: configService.get('auth.jwtSecret'),

View File

@ -9,7 +9,10 @@ import cachedResponse from './assets/cachedResponse.json';
@Injectable() @Injectable()
export class FontsService { export class FontsService {
constructor(private configService: ConfigService, private httpService: HttpService) {} constructor(
private configService: ConfigService,
private httpService: HttpService,
) {}
async getAll(): Promise<Font[]> { async getAll(): Promise<Font[]> {
const apiKey = this.configService.get('google.apiKey'); const apiKey = this.configService.get('google.apiKey');

View File

@ -6,7 +6,7 @@ export class HealthController {
constructor( constructor(
private health: HealthCheckService, private health: HealthCheckService,
private http: HttpHealthIndicator, private http: HttpHealthIndicator,
private db: TypeOrmHealthIndicator private db: TypeOrmHealthIndicator,
) {} ) {}
@Get() @Get()

View File

@ -10,7 +10,7 @@ export class PrinterController {
async printAsPdf( async printAsPdf(
@Param('username') username: string, @Param('username') username: string,
@Param('slug') slug: string, @Param('slug') slug: string,
@Query('lastUpdated') lastUpdated: string @Query('lastUpdated') lastUpdated: string,
): Promise<string> { ): Promise<string> {
try { try {
return await this.printerService.printAsPdf(username, slug, lastUpdated); return await this.printerService.printAsPdf(username, slug, lastUpdated);

View File

@ -49,7 +49,10 @@ const minimal_chromium_args = [
export class PrinterService implements OnModuleInit, OnModuleDestroy { export class PrinterService implements OnModuleInit, OnModuleDestroy {
private browser: BrowserContext; private browser: BrowserContext;
constructor(private readonly schedulerRegistry: SchedulerRegistry, private readonly configService: ConfigService) {} constructor(
private readonly schedulerRegistry: SchedulerRegistry,
private readonly configService: ConfigService,
) {}
async onModuleInit() { async onModuleInit() {
this.browser = await chromium.launchPersistentContext('.playwright', { this.browser = await chromium.launchPersistentContext('.playwright', {
@ -84,7 +87,7 @@ export class PrinterService implements OnModuleInit, OnModuleDestroy {
this.schedulerRegistry.deleteTimeout(`delete-${file}`); this.schedulerRegistry.deleteTimeout(`delete-${file}`);
} }
} }
}) }),
); );
}); });
@ -99,7 +102,7 @@ export class PrinterService implements OnModuleInit, OnModuleDestroy {
const pageFormat: PageConfig['format'] = await page.$$eval( const pageFormat: PageConfig['format'] = await page.$$eval(
'[data-page]', '[data-page]',
(pages) => pages[0].getAttribute('data-format') as PageConfig['format'] (pages) => pages[0].getAttribute('data-format') as PageConfig['format'],
); );
const resumePages = await page.$$eval('[data-page]', (pages) => const resumePages = await page.$$eval('[data-page]', (pages) =>
@ -107,7 +110,7 @@ export class PrinterService implements OnModuleInit, OnModuleDestroy {
pageNumber: index + 1, pageNumber: index + 1,
innerHTML: page.innerHTML, innerHTML: page.innerHTML,
height: page.clientHeight, height: page.clientHeight,
})) })),
); );
const pdf = await PDFDocument.create(); const pdf = await PDFDocument.create();

View File

@ -43,7 +43,7 @@ export class ResumeController {
findOneByShortId( findOneByShortId(
@Param('shortId') shortId: string, @Param('shortId') shortId: string,
@User('id') userId?: number, @User('id') userId?: number,
@Query('secretKey') secretKey?: string @Query('secretKey') secretKey?: string,
) { ) {
return this.resumeService.findOneByShortId(shortId, userId, secretKey); return this.resumeService.findOneByShortId(shortId, userId, secretKey);
} }
@ -54,7 +54,7 @@ export class ResumeController {
@Param('username') username: string, @Param('username') username: string,
@Param('slug') slug: string, @Param('slug') slug: string,
@User('id') userId?: number, @User('id') userId?: number,
@Query('secretKey') secretKey?: string @Query('secretKey') secretKey?: string,
) { ) {
return this.resumeService.findOneByIdentifier(username, slug, userId, secretKey); return this.resumeService.findOneByIdentifier(username, slug, userId, secretKey);
} }

View File

@ -19,7 +19,7 @@ export class UsersService {
@InjectRepository(User) private userRepository: Repository<User>, @InjectRepository(User) private userRepository: Repository<User>,
private schedulerRegistry: SchedulerRegistry, private schedulerRegistry: SchedulerRegistry,
private mailService: MailService, private mailService: MailService,
private dataSource: DataSource private dataSource: DataSource,
) {} ) {}
async findById(id: number): Promise<User> { async findById(id: number): Promise<User> {
@ -115,7 +115,7 @@ export class UsersService {
throw new HttpException( throw new HttpException(
'Please wait at least 30 minutes before resetting your password again.', 'Please wait at least 30 minutes before resetting your password again.',
HttpStatus.TOO_MANY_REQUESTS HttpStatus.TOO_MANY_REQUESTS,
); );
} finally { } finally {
await queryRunner.release(); await queryRunner.release();