mirror of
https://github.com/Sonny93/my-links.git
synced 2025-12-08 22:53:25 +00:00
feat: bring back legal pages
This commit is contained in:
@@ -3,10 +3,6 @@ import { updateUserThemeValidator } from '#validators/user';
|
|||||||
import type { HttpContext } from '@adonisjs/core/http';
|
import type { HttpContext } from '@adonisjs/core/http';
|
||||||
|
|
||||||
export default class AppsController {
|
export default class AppsController {
|
||||||
index({ inertia }: HttpContext) {
|
|
||||||
return inertia.render('home');
|
|
||||||
}
|
|
||||||
|
|
||||||
async updateUserTheme({ request, session, response }: HttpContext) {
|
async updateUserTheme({ request, session, response }: HttpContext) {
|
||||||
const { preferDarkTheme } = await request.validateUsing(
|
const { preferDarkTheme } = await request.validateUsing(
|
||||||
updateUserThemeValidator
|
updateUserThemeValidator
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import styled from '@emotion/styled';
|
import styled from '@emotion/styled';
|
||||||
|
|
||||||
const DropdownLabel = styled.p(({ theme }) => ({
|
const DropdownLabel = styled.div(({ theme }) => ({
|
||||||
height: 'auto',
|
height: 'auto',
|
||||||
width: 'auto',
|
width: 'auto',
|
||||||
color: theme.colors.font,
|
color: theme.colors.font,
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ const HeroStyle = styled.header(({ theme }) => ({
|
|||||||
height: '250px',
|
height: '250px',
|
||||||
minHeight: '250px',
|
minHeight: '250px',
|
||||||
width: '100%',
|
width: '100%',
|
||||||
backgroundColor: theme.colors.darkestBlue,
|
backgroundColor: theme.colors.secondary,
|
||||||
marginTop: '0.5em',
|
marginTop: '0.5em',
|
||||||
borderRadius: theme.border.radius,
|
borderRadius: theme.border.radius,
|
||||||
padding: '1em',
|
padding: '1em',
|
||||||
@@ -19,7 +19,6 @@ const HeroStyle = styled.header(({ theme }) => ({
|
|||||||
flexDirection: 'column',
|
flexDirection: 'column',
|
||||||
|
|
||||||
'& *': {
|
'& *': {
|
||||||
color: `${theme.colors.white} !important`,
|
|
||||||
textAlign: 'center',
|
textAlign: 'center',
|
||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
@@ -35,6 +34,7 @@ const HeroQuote = styled(Quotes)({
|
|||||||
const LinkButton = styled(Link)(({ theme }) => ({
|
const LinkButton = styled(Link)(({ theme }) => ({
|
||||||
fontSize: '1rem',
|
fontSize: '1rem',
|
||||||
width: 'fit-content',
|
width: 'fit-content',
|
||||||
|
color: theme.colors.white,
|
||||||
backgroundColor: theme.colors.primary,
|
backgroundColor: theme.colors.primary,
|
||||||
borderRadius: '5rem',
|
borderRadius: '5rem',
|
||||||
padding: '0.5em 1.5em',
|
padding: '0.5em 1.5em',
|
||||||
|
|||||||
36
inertia/components/layouts/legal_content_layout.tsx
Normal file
36
inertia/components/layouts/legal_content_layout.tsx
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
import styled from '@emotion/styled';
|
||||||
|
import { ReactNode } from 'react';
|
||||||
|
import ContentLayout from '~/components/layouts/content_layout';
|
||||||
|
import LegalFooter from '~/components/legal/legal_footer';
|
||||||
|
|
||||||
|
const LegalContentStyle = styled(ContentLayout)({
|
||||||
|
main: {
|
||||||
|
'h1, p': {
|
||||||
|
marginTop: '0.5em',
|
||||||
|
},
|
||||||
|
h2: {
|
||||||
|
marginTop: '1.5em',
|
||||||
|
},
|
||||||
|
h3: {
|
||||||
|
marginTop: '1em',
|
||||||
|
},
|
||||||
|
ul: {
|
||||||
|
marginLeft: '2em',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const LegalContentLayout = ({
|
||||||
|
children,
|
||||||
|
className,
|
||||||
|
}: {
|
||||||
|
children: ReactNode;
|
||||||
|
className?: string;
|
||||||
|
}) => (
|
||||||
|
<LegalContentStyle className={className}>
|
||||||
|
{children}
|
||||||
|
<LegalFooter />
|
||||||
|
</LegalContentStyle>
|
||||||
|
);
|
||||||
|
|
||||||
|
export default LegalContentLayout;
|
||||||
20
inertia/components/legal/legal_footer.tsx
Normal file
20
inertia/components/legal/legal_footer.tsx
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import ExternalLink from '~/components/common/external_link';
|
||||||
|
|
||||||
|
export default function LegalFooter() {
|
||||||
|
const { t } = useTranslation('legal');
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<h2>{t('contact.title')}</h2>
|
||||||
|
<p>
|
||||||
|
{t('contact.description')}{' '}
|
||||||
|
<ExternalLink href="mailto:sonnyasdev@gmail.com" target="_blank">
|
||||||
|
sonnyasdev[at]gmail[dot]com
|
||||||
|
</ExternalLink>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>{t('footer.changes')}</p>
|
||||||
|
<p css={{ marginBottom: '2em' }}>{t('footer.thanks')}</p>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -9,8 +9,10 @@ import frResourceAdmin from './locales/fr/admin.json';
|
|||||||
import frResourceCommon from './locales/fr/common.json';
|
import frResourceCommon from './locales/fr/common.json';
|
||||||
import frResourceHome from './locales/fr/home.json';
|
import frResourceHome from './locales/fr/home.json';
|
||||||
import frResourceLogin from './locales/fr/login.json';
|
import frResourceLogin from './locales/fr/login.json';
|
||||||
|
|
||||||
import frResourcePrivacy from './locales/fr/privacy.json';
|
import frResourcePrivacy from './locales/fr/privacy.json';
|
||||||
import frResourceTerms from './locales/fr/terms.json';
|
import frResourceTerms from './locales/fr/terms.json';
|
||||||
|
import frResourceLegal from './locales/fr/legal.json';
|
||||||
|
|
||||||
import { LS_LANG_KEY } from '~/constants';
|
import { LS_LANG_KEY } from '~/constants';
|
||||||
import enResourceAbout from './locales/en/about.json';
|
import enResourceAbout from './locales/en/about.json';
|
||||||
@@ -18,8 +20,10 @@ import enResourceAdmin from './locales/en/admin.json';
|
|||||||
import enResourceCommon from './locales/en/common.json';
|
import enResourceCommon from './locales/en/common.json';
|
||||||
import enResourceHome from './locales/en/home.json';
|
import enResourceHome from './locales/en/home.json';
|
||||||
import enResourceLogin from './locales/en/login.json';
|
import enResourceLogin from './locales/en/login.json';
|
||||||
|
|
||||||
import enResourcePrivacy from './locales/en/privacy.json';
|
import enResourcePrivacy from './locales/en/privacy.json';
|
||||||
import enResourceTerms from './locales/en/terms.json';
|
import enResourceTerms from './locales/en/terms.json';
|
||||||
|
import enResourceLegal from './locales/en/legal.json';
|
||||||
|
|
||||||
type I18nFR =
|
type I18nFR =
|
||||||
| RemoveSuffix<Leaves<typeof frResourceAbout>>
|
| RemoveSuffix<Leaves<typeof frResourceAbout>>
|
||||||
@@ -28,7 +32,8 @@ type I18nFR =
|
|||||||
| RemoveSuffix<Leaves<typeof frResourceHome>>
|
| RemoveSuffix<Leaves<typeof frResourceHome>>
|
||||||
| RemoveSuffix<Leaves<typeof frResourceLogin>>
|
| RemoveSuffix<Leaves<typeof frResourceLogin>>
|
||||||
| RemoveSuffix<Leaves<typeof frResourcePrivacy>>
|
| RemoveSuffix<Leaves<typeof frResourcePrivacy>>
|
||||||
| RemoveSuffix<Leaves<typeof frResourceTerms>>;
|
| RemoveSuffix<Leaves<typeof frResourceTerms>>
|
||||||
|
| RemoveSuffix<Leaves<typeof frResourceLegal>>;
|
||||||
export type I18nKey = I18nFR;
|
export type I18nKey = I18nFR;
|
||||||
|
|
||||||
export const resources = {
|
export const resources = {
|
||||||
@@ -40,6 +45,7 @@ export const resources = {
|
|||||||
login: enResourceLogin,
|
login: enResourceLogin,
|
||||||
privacy: enResourcePrivacy,
|
privacy: enResourcePrivacy,
|
||||||
terms: enResourceTerms,
|
terms: enResourceTerms,
|
||||||
|
legal: enResourceLegal,
|
||||||
},
|
},
|
||||||
fr: {
|
fr: {
|
||||||
about: frResourceAbout,
|
about: frResourceAbout,
|
||||||
@@ -49,6 +55,7 @@ export const resources = {
|
|||||||
login: frResourceLogin,
|
login: frResourceLogin,
|
||||||
privacy: frResourcePrivacy,
|
privacy: frResourcePrivacy,
|
||||||
terms: frResourceTerms,
|
terms: frResourceTerms,
|
||||||
|
legal: frResourceLegal,
|
||||||
},
|
},
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
|
|||||||
10
inertia/i18n/locales/en/legal.json
Normal file
10
inertia/i18n/locales/en/legal.json
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"contact": {
|
||||||
|
"title": "Contact",
|
||||||
|
"description": "For any questions or concerns regarding these Terms and Conditions of Use, please contact us at the following address:"
|
||||||
|
},
|
||||||
|
"footer": {
|
||||||
|
"changes": "We reserve the right to update these Terms and Conditions of Use. We encourage you to regularly check this page to stay informed of any changes.",
|
||||||
|
"thanks": "Thank you for using MyLinks!"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -39,13 +39,5 @@
|
|||||||
"gdpr": {
|
"gdpr": {
|
||||||
"title": "5. GDPR Compliance",
|
"title": "5. GDPR Compliance",
|
||||||
"description": "MyLinks complies with the General Data Protection Regulation (GDPR) of the European Union."
|
"description": "MyLinks complies with the General Data Protection Regulation (GDPR) of the European Union."
|
||||||
},
|
|
||||||
"contact": {
|
|
||||||
"title": "6. Contact",
|
|
||||||
"description": "If you have any questions or concerns about our privacy policy, feel free to contact us at the following address:"
|
|
||||||
},
|
|
||||||
"footer": {
|
|
||||||
"changes": "We reserve the right to update this privacy policy. We encourage you to regularly check this page to stay informed of any changes.",
|
|
||||||
"thanks": "Thank you for using MyLinks!"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -50,13 +50,5 @@
|
|||||||
"cancel": {
|
"cancel": {
|
||||||
"title": "6. Termination",
|
"title": "6. Termination",
|
||||||
"description": "MyLinks reserves the right to terminate or suspend your access to the service, with or without notice, in case of violation of these Terms and Conditions of Use."
|
"description": "MyLinks reserves the right to terminate or suspend your access to the service, with or without notice, in case of violation of these Terms and Conditions of Use."
|
||||||
},
|
|
||||||
"contact": {
|
|
||||||
"title": "7. Contact",
|
|
||||||
"description": "For any questions or concerns regarding these Terms and Conditions of Use, please contact us at the following address:"
|
|
||||||
},
|
|
||||||
"footer": {
|
|
||||||
"changes": "We reserve the right to update these Terms and Conditions of Use. We encourage you to regularly check this page to stay informed of any changes.",
|
|
||||||
"thanks": "Thank you for using MyLinks!"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
10
inertia/i18n/locales/fr/legal.json
Normal file
10
inertia/i18n/locales/fr/legal.json
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"contact": {
|
||||||
|
"title": "Contact",
|
||||||
|
"description": "Pour toute question ou préoccupation concernant ces Conditions Générales d'Utilisation, veuillez nous contacter à l'adresse suivante :"
|
||||||
|
},
|
||||||
|
"footer": {
|
||||||
|
"changes": "Nous nous réservons le droit de mettre à jour ces Conditions Générales d'Utilisation. Nous vous encourageons à consulter régulièrement cette page pour rester informé des changements éventuels.",
|
||||||
|
"thanks": "Merci d'utiliser MyLinks !"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -39,13 +39,5 @@
|
|||||||
"gdpr": {
|
"gdpr": {
|
||||||
"title": "5. Conformité au RGPD",
|
"title": "5. Conformité au RGPD",
|
||||||
"description": "MyLinks est conforme au Règlement Général sur la Protection des Données (RGPD) de l'Union européenne."
|
"description": "MyLinks est conforme au Règlement Général sur la Protection des Données (RGPD) de l'Union européenne."
|
||||||
},
|
|
||||||
"contact": {
|
|
||||||
"title": "6. Contact",
|
|
||||||
"description": "Si vous avez des questions ou des préoccupations concernant notre politique de confidentialité, n'hésitez pas à nous contacter à l'adresse suivante :"
|
|
||||||
},
|
|
||||||
"footer": {
|
|
||||||
"changes": "Nous nous réservons le droit de mettre à jour cette politique de confidentialité. Nous vous encourageons à consulter régulièrement cette page pour rester informé des changements éventuels.",
|
|
||||||
"thanks": "Merci d'utiliser MyLinks !"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -50,13 +50,5 @@
|
|||||||
"cancel": {
|
"cancel": {
|
||||||
"title": "6. Résiliation",
|
"title": "6. Résiliation",
|
||||||
"description": "MyLinks se réserve le droit de résilier ou de suspendre votre accès au service, avec ou sans préavis, en cas de violation de ces Conditions Générales d'Utilisation."
|
"description": "MyLinks se réserve le droit de résilier ou de suspendre votre accès au service, avec ou sans préavis, en cas de violation de ces Conditions Générales d'Utilisation."
|
||||||
},
|
|
||||||
"contact": {
|
|
||||||
"title": "7. Contact",
|
|
||||||
"description": "Pour toute question ou préoccupation concernant ces Conditions Générales d'Utilisation, veuillez nous contacter à l'adresse suivante :"
|
|
||||||
},
|
|
||||||
"footer": {
|
|
||||||
"changes": "Nous nous réservons le droit de mettre à jour ces Conditions Générales d'Utilisation. Nous vous encourageons à consulter régulièrement cette page pour rester informé des changements éventuels.",
|
|
||||||
"thanks": "Merci d'utiliser MyLinks !"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -19,7 +19,7 @@ const PageContent = styled.div({
|
|||||||
flexDirection: 'column',
|
flexDirection: 'column',
|
||||||
});
|
});
|
||||||
|
|
||||||
export default function Home() {
|
export default function HomePage() {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
return (
|
return (
|
||||||
<ContentLayout>
|
<ContentLayout>
|
||||||
|
|||||||
44
inertia/pages/privacy.tsx
Normal file
44
inertia/pages/privacy.tsx
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import LegalContentLayout from '~/components/layouts/legal_content_layout';
|
||||||
|
|
||||||
|
export default function TermsPage() {
|
||||||
|
const { t } = useTranslation('privacy');
|
||||||
|
return (
|
||||||
|
<LegalContentLayout>
|
||||||
|
<h1>{t('title')}</h1>
|
||||||
|
<p>{t('edited_at', { date: '19/11/2023' })}</p>
|
||||||
|
<p>{t('welcome')}</p>
|
||||||
|
|
||||||
|
<h2>{t('collect.title')}</h2>
|
||||||
|
<h3>{t('collect.cookie.title')}</h3>
|
||||||
|
<p>{t('collect.cookie.description')}</p>
|
||||||
|
|
||||||
|
<h3>{t('collect.user.title')}</h3>
|
||||||
|
<p>{t('collect.user.description')}</p>
|
||||||
|
<ul>
|
||||||
|
{(
|
||||||
|
t('collect.user.fields', {
|
||||||
|
returnObjects: true,
|
||||||
|
}) as Array<string>
|
||||||
|
).map((field) => (
|
||||||
|
<li key={field}>{field}</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h2>{t('data_use.title')}</h2>
|
||||||
|
<p>{t('data_use.description')}</p>
|
||||||
|
|
||||||
|
<h2>{t('data_storage.title')}</h2>
|
||||||
|
<p>{t('data_storage.description')}</p>
|
||||||
|
|
||||||
|
<h3>{t('data_storage.data_retention.title')}</h3>
|
||||||
|
<p>{t('data_storage.data_retention.description')}</p>
|
||||||
|
|
||||||
|
<h2>{t('user_rights.title')}</h2>
|
||||||
|
<p>{t('user_rights.description')}</p>
|
||||||
|
|
||||||
|
<h2>{t('gdpr.title')}</h2>
|
||||||
|
<p>{t('gdpr.description')}</p>
|
||||||
|
</LegalContentLayout>
|
||||||
|
);
|
||||||
|
}
|
||||||
53
inertia/pages/terms.tsx
Normal file
53
inertia/pages/terms.tsx
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
import { Link } from '@inertiajs/react';
|
||||||
|
import { route } from '@izzyjs/route/client';
|
||||||
|
import { Trans, useTranslation } from 'react-i18next';
|
||||||
|
import LegalContentLayout from '~/components/layouts/legal_content_layout';
|
||||||
|
|
||||||
|
export default function TermsPage() {
|
||||||
|
const { t } = useTranslation('terms');
|
||||||
|
return (
|
||||||
|
<LegalContentLayout>
|
||||||
|
<h1>{t('title')}</h1>
|
||||||
|
<p>{t('edited_at', { date: '19/11/2023' })}</p>
|
||||||
|
<p>{t('welcome')}</p>
|
||||||
|
|
||||||
|
<h2>{t('accept.title')}</h2>
|
||||||
|
<p>{t('accept.description')}</p>
|
||||||
|
|
||||||
|
<h2>{t('use.title')}</h2>
|
||||||
|
<h3>{t('use.account.title')}</h3>
|
||||||
|
<p>{t('use.account.description')}</p>
|
||||||
|
|
||||||
|
<h3>{t('use.allowed.title')}</h3>
|
||||||
|
<p>{t('use.allowed.description')}</p>
|
||||||
|
|
||||||
|
<h3>{t('use.user_content.title')}</h3>
|
||||||
|
<p>{t('use.user_content.description')}</p>
|
||||||
|
|
||||||
|
<h2>{t('personal_data.title')}</h2>
|
||||||
|
<h3>{t('personal_data.collect.title')}</h3>
|
||||||
|
<p>
|
||||||
|
<Trans
|
||||||
|
i18nKey="personal_data.collect.description"
|
||||||
|
components={{ a: <Link href={route('privacy').url} /> }}
|
||||||
|
/>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3>{t('personal_data.suppress.title')}</h3>
|
||||||
|
<p>{t('personal_data.suppress.description')}</p>
|
||||||
|
|
||||||
|
<h2>{t('responsibility_warranty.title')}</h2>
|
||||||
|
<h3>{t('responsibility_warranty.responsibility.title')}</h3>
|
||||||
|
<p>{t('responsibility_warranty.responsibility.description')}</p>
|
||||||
|
|
||||||
|
<h3>{t('responsibility_warranty.warranty.title')}</h3>
|
||||||
|
<p>{t('responsibility_warranty.warranty.description')}</p>
|
||||||
|
|
||||||
|
<h2>{t('terms_changes.title')}</h2>
|
||||||
|
<p>{t('terms_changes.description')}</p>
|
||||||
|
|
||||||
|
<h2>{t('cancel.title')}</h2>
|
||||||
|
<p>{t('cancel.description')}</p>
|
||||||
|
</LegalContentLayout>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -5,9 +5,9 @@ const AppsController = () => import('#controllers/apps_controller');
|
|||||||
* All routes for both logged and guest users
|
* All routes for both logged and guest users
|
||||||
*/
|
*/
|
||||||
router.group(() => {
|
router.group(() => {
|
||||||
router.get('/', [AppsController, 'index']).as('home');
|
router.on('/').renderInertia('home').as('home');
|
||||||
router.get('/privacy', () => 'privacy').as('privacy');
|
router.on('/terms').renderInertia('terms').as('terms');
|
||||||
router.get('/terms', () => 'terms').as('terms');
|
router.on('/privacy').renderInertia('privacy').as('privacy');
|
||||||
|
|
||||||
router
|
router
|
||||||
.post('/user/theme', [AppsController, 'updateUserTheme'])
|
.post('/user/theme', [AppsController, 'updateUserTheme'])
|
||||||
|
|||||||
Reference in New Issue
Block a user