mirror of
https://github.com/AmruthPillai/Reactive-Resume.git
synced 2025-11-14 00:32:35 +10:00
fix(client): 🐛 do not allow private resumes to be viewable or downloadable through the link
This commit is contained in:
@ -63,12 +63,12 @@ const Avatar: React.FC<Props> = ({ size = 64, interactive = true }) => {
|
||||
<Menu anchorEl={anchorEl} onClose={handleClose} open={Boolean(anchorEl)}>
|
||||
<MenuItem onClick={handleOpenProfile}>
|
||||
<div>
|
||||
<span className="text-xs opacity-50">{t<string>('common.avatar.menu.greeting')},</span>
|
||||
<span className="text-xs opacity-50">{t('common.avatar.menu.greeting')},</span>
|
||||
<p>{user?.name}</p>
|
||||
</div>
|
||||
</MenuItem>
|
||||
<Divider />
|
||||
<MenuItem onClick={handleLogout}>{t<string>('common.avatar.menu.logout')}</MenuItem>
|
||||
<MenuItem onClick={handleLogout}>{t('common.avatar.menu.logout')}</MenuItem>
|
||||
</Menu>
|
||||
</>
|
||||
);
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
.content {
|
||||
@apply rounded px-6 text-sm shadow lg:w-1/2 xl:w-2/5;
|
||||
@apply absolute inset-4 sm:inset-x-4 sm:inset-y-auto lg:inset-auto;
|
||||
@apply overflow-scroll bg-neutral-50 dark:bg-neutral-900 lg:overflow-auto;
|
||||
@apply overflow-scroll bg-zinc-100 dark:bg-zinc-900 lg:overflow-auto;
|
||||
@apply max-h-[90vh] min-h-fit;
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
@ -10,7 +10,7 @@
|
||||
}
|
||||
|
||||
.header {
|
||||
@apply sticky top-0 left-0 right-0 z-50 bg-neutral-50 pt-6 dark:bg-neutral-900;
|
||||
@apply sticky top-0 left-0 right-0 z-50 bg-zinc-100 pt-6 dark:bg-zinc-900;
|
||||
@apply flex items-center justify-between;
|
||||
@apply w-full border-b pb-5 dark:border-white/10;
|
||||
|
||||
@ -33,7 +33,7 @@
|
||||
}
|
||||
|
||||
.footer {
|
||||
@apply sticky bottom-0 left-0 right-0 z-50 bg-neutral-50 pb-6 dark:bg-neutral-900;
|
||||
@apply sticky bottom-0 left-0 right-0 z-50 bg-zinc-100 pb-6 dark:bg-zinc-900;
|
||||
@apply flex items-center justify-end gap-x-4;
|
||||
@apply w-full border-t pt-5 dark:border-white/10;
|
||||
}
|
||||
|
||||
19
client/components/shared/Copyright.tsx
Normal file
19
client/components/shared/Copyright.tsx
Normal file
@ -0,0 +1,19 @@
|
||||
import clsx from 'clsx';
|
||||
|
||||
type Props = {
|
||||
className?: string;
|
||||
};
|
||||
|
||||
export const Copyright = ({ className }: Props) => (
|
||||
<div
|
||||
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>
|
||||
Licensed under <a href="https://github.com/AmruthPillai/Reactive-Resume/blob/main/LICENSE">MIT</a>
|
||||
</span>
|
||||
<span>
|
||||
A passion project by <a href="https://www.amruthpillai.com/">Amruth Pillai</a>
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
@ -10,7 +10,7 @@ const Footer: React.FC<Props> = ({ className }) => {
|
||||
|
||||
return (
|
||||
<div className={clsx('text-xs', className)}>
|
||||
<p>{t<string>('common.footer.license')}</p>
|
||||
<p>{t('common.footer.license')}</p>
|
||||
|
||||
<p>
|
||||
<Trans t={t} i18nKey="common.footer.credit">
|
||||
|
||||
@ -62,7 +62,7 @@ const Heading: React.FC<Props> = ({
|
||||
{editMode ? (
|
||||
<TextField size="small" value={heading} className="w-3/4" onChange={handleChange} />
|
||||
) : (
|
||||
<h1>{t<string>(`builder.leftSidebar.${path}.heading`, { defaultValue: heading })}</h1>
|
||||
<h1>{t(`builder.leftSidebar.${path}.heading`, { defaultValue: heading })}</h1>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@ -72,19 +72,19 @@ const Heading: React.FC<Props> = ({
|
||||
})}
|
||||
>
|
||||
{isEditable && (
|
||||
<Tooltip title={t<string>('builder.common.tooltip.rename-section')}>
|
||||
<Tooltip title={t('builder.common.tooltip.rename-section')}>
|
||||
<IconButton onClick={toggleEditMode}>{editMode ? <Check /> : <DriveFileRenameOutline />}</IconButton>
|
||||
</Tooltip>
|
||||
)}
|
||||
|
||||
{isHideable && (
|
||||
<Tooltip title={t<string>('builder.common.tooltip.toggle-visibility')}>
|
||||
<Tooltip title={t('builder.common.tooltip.toggle-visibility')}>
|
||||
<IconButton onClick={toggleVisibility}>{visibility ? <Visibility /> : <VisibilityOff />}</IconButton>
|
||||
</Tooltip>
|
||||
)}
|
||||
|
||||
{isDeletable && (
|
||||
<Tooltip title={t<string>('builder.common.tooltip.delete-section')}>
|
||||
<Tooltip title={t('builder.common.tooltip.delete-section')}>
|
||||
<IconButton onClick={handleDelete}>
|
||||
<Delete />
|
||||
</IconButton>
|
||||
|
||||
27
client/components/shared/Icon.tsx
Normal file
27
client/components/shared/Icon.tsx
Normal file
@ -0,0 +1,27 @@
|
||||
import clsx from 'clsx';
|
||||
import Image from 'next/image';
|
||||
|
||||
import { useAppSelector } from '@/store/hooks';
|
||||
|
||||
type Props = {
|
||||
className?: string;
|
||||
size?: 256 | 96 | 64 | 48 | 40 | 32 | 24 | 16;
|
||||
};
|
||||
|
||||
const Icon: React.FC<Props> = ({ size = 64, className }) => {
|
||||
const theme = useAppSelector((state) => state.build.theme);
|
||||
const iconTheme = theme === 'light' ? 'dark' : 'light';
|
||||
|
||||
return (
|
||||
<Image
|
||||
alt="Reactive Resume"
|
||||
src={`/icon/${iconTheme}.svg`}
|
||||
className={clsx('rounded', className)}
|
||||
width={size}
|
||||
height={size}
|
||||
priority
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default Icon;
|
||||
@ -1,5 +1,5 @@
|
||||
.container {
|
||||
@apply rounded-lg border dark:border-neutral-50/10;
|
||||
@apply rounded-lg border dark:border-zinc-50/10;
|
||||
|
||||
.empty {
|
||||
@apply py-8 text-center;
|
||||
|
||||
@ -60,13 +60,13 @@ const List: React.FC<Props> = ({
|
||||
|
||||
dispatch(setResumeState({ path, value: newList }));
|
||||
},
|
||||
[list, dispatch, path]
|
||||
[list, dispatch, path],
|
||||
);
|
||||
|
||||
return (
|
||||
<DndProvider backend={HTML5Backend}>
|
||||
<div className={clsx(styles.container, className)}>
|
||||
{isEmpty(list) && <div className={styles.empty}>{t<string>('builder.common.list.empty-text')}</div>}
|
||||
{isEmpty(list) && <div className={styles.empty}>{t('builder.common.list.empty-text')}</div>}
|
||||
|
||||
{list.map((item, index) => {
|
||||
const title = get(item, titleKey, '');
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
.item {
|
||||
@apply flex items-center justify-between;
|
||||
@apply py-5 pl-5 pr-2;
|
||||
@apply border-b border-neutral-900/10 last:border-0 dark:border-neutral-50/10;
|
||||
@apply border-b border-zinc-900/10 last:border-0 dark:border-zinc-50/10;
|
||||
@apply cursor-move transition-opacity;
|
||||
|
||||
.meta {
|
||||
|
||||
@ -126,25 +126,25 @@ const ListItem: React.FC<Props> = ({ item, path, index, title, subtitle, onMove,
|
||||
<ListItemIcon>
|
||||
<DriveFileRenameOutline className="scale-90" />
|
||||
</ListItemIcon>
|
||||
<ListItemText>{t<string>('builder.common.list.actions.edit')}</ListItemText>
|
||||
<ListItemText>{t('builder.common.list.actions.edit')}</ListItemText>
|
||||
</MenuItem>
|
||||
|
||||
<MenuItem onClick={() => handleDuplicate(item)}>
|
||||
<ListItemIcon>
|
||||
<FileCopy className="scale-90" />
|
||||
</ListItemIcon>
|
||||
<ListItemText>{t<string>('builder.common.list.actions.duplicate')}</ListItemText>
|
||||
<ListItemText>{t('builder.common.list.actions.duplicate')}</ListItemText>
|
||||
</MenuItem>
|
||||
|
||||
<Divider />
|
||||
|
||||
<Tooltip arrow placement="right" title={t<string>('builder.common.tooltip.delete-item')}>
|
||||
<Tooltip arrow placement="right" title={t('builder.common.tooltip.delete-item')}>
|
||||
<div>
|
||||
<MenuItem onClick={() => handleDelete(item)}>
|
||||
<ListItemIcon>
|
||||
<DeleteOutline className="scale-90" />
|
||||
</ListItemIcon>
|
||||
<ListItemText>{t<string>('builder.common.list.actions.delete')}</ListItemText>
|
||||
<ListItemText>{t('builder.common.list.actions.delete')}</ListItemText>
|
||||
</MenuItem>
|
||||
</div>
|
||||
</Tooltip>
|
||||
|
||||
@ -1,11 +1,26 @@
|
||||
import clsx from 'clsx';
|
||||
import Image from 'next/image';
|
||||
|
||||
import { useAppSelector } from '@/store/hooks';
|
||||
|
||||
type Props = {
|
||||
size?: 256 | 64 | 48 | 40 | 32;
|
||||
className?: string;
|
||||
size?: 256 | 96 | 64 | 48 | 40 | 32 | 24 | 16;
|
||||
};
|
||||
|
||||
const Logo: React.FC<Props> = ({ size = 64 }) => (
|
||||
<Image alt="Reactive Resume" src="/images/logos/logo.svg" className="rounded" width={size} height={size} priority />
|
||||
);
|
||||
const Logo: React.FC<Props> = ({ size = 64, className }) => {
|
||||
const theme = useAppSelector((state) => state.build.theme);
|
||||
|
||||
return (
|
||||
<Image
|
||||
alt="Reactive Resume"
|
||||
src={`/logo/${theme}.svg`}
|
||||
className={clsx('rounded', className)}
|
||||
width={size}
|
||||
height={size}
|
||||
priority
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default Logo;
|
||||
|
||||
Reference in New Issue
Block a user