Add contact, privacy, and terms pages with localization support
- Implemented contact page with form submission functionality and email integration. - Created privacy and terms pages with structured content and localization. - Updated English and French localization files to include new strings for contact, privacy, and terms. - Enhanced About page with detailed sections on mission, technology, security, and tools offered.
This commit is contained in:
@@ -1,50 +1,103 @@
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Helmet } from 'react-helmet-async';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { Target, Cpu, Shield, Lock, Wrench } from 'lucide-react';
|
||||
import { FILE_RETENTION_MINUTES } from '@/config/toolLimits';
|
||||
|
||||
export default function AboutPage() {
|
||||
const { t } = useTranslation();
|
||||
const toolCategories = t('pages.about.toolCategories', { returnObjects: true }) as string[];
|
||||
|
||||
return (
|
||||
<>
|
||||
<Helmet>
|
||||
<title>{t('common.about')} — {t('common.appName')}</title>
|
||||
<meta name="description" content="About our free online file conversion tools." />
|
||||
<title>{t('pages.about.title')} — {t('common.appName')}</title>
|
||||
<meta name="description" content={t('pages.about.metaDescription')} />
|
||||
<link rel="canonical" href={`${window.location.origin}/about`} />
|
||||
</Helmet>
|
||||
|
||||
<div className="prose mx-auto max-w-2xl dark:prose-invert">
|
||||
<h1>{t('common.about')}</h1>
|
||||
<div className="mx-auto max-w-3xl">
|
||||
<h1 className="mb-8 text-3xl font-bold text-slate-900 dark:text-white">
|
||||
{t('pages.about.title')}
|
||||
</h1>
|
||||
|
||||
<p>
|
||||
We provide free, fast, and secure online tools for converting, compressing,
|
||||
and processing files — PDFs, images, videos, and text.
|
||||
</p>
|
||||
{/* Mission */}
|
||||
<section className="mb-10">
|
||||
<div className="flex items-center gap-3 mb-3">
|
||||
<Target className="h-6 w-6 text-primary-600 dark:text-primary-400" />
|
||||
<h2 className="text-xl font-semibold text-slate-900 dark:text-white">
|
||||
{t('pages.about.missionTitle')}
|
||||
</h2>
|
||||
</div>
|
||||
<p className="text-slate-600 dark:text-slate-400 leading-relaxed">
|
||||
{t('pages.about.missionText')}
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<h2>Why use our tools?</h2>
|
||||
<ul>
|
||||
<li><strong>100% Free</strong> — No hidden charges, no sign-up required.</li>
|
||||
<li><strong>Private & Secure</strong> — Files are auto-deleted within {FILE_RETENTION_MINUTES} minutes.</li>
|
||||
<li><strong>Fast Processing</strong> — Server-side processing for reliable results.</li>
|
||||
<li><strong>Works Everywhere</strong> — Desktop, tablet, or mobile.</li>
|
||||
</ul>
|
||||
{/* Technology */}
|
||||
<section className="mb-10">
|
||||
<div className="flex items-center gap-3 mb-3">
|
||||
<Cpu className="h-6 w-6 text-primary-600 dark:text-primary-400" />
|
||||
<h2 className="text-xl font-semibold text-slate-900 dark:text-white">
|
||||
{t('pages.about.technologyTitle')}
|
||||
</h2>
|
||||
</div>
|
||||
<p className="text-slate-600 dark:text-slate-400 leading-relaxed">
|
||||
{t('pages.about.technologyText')}
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<h2>Available Tools</h2>
|
||||
<ul>
|
||||
<li>PDF conversion tools (PDF↔Word)</li>
|
||||
<li>PDF optimization and utility tools (compress, merge, split, rotate, page numbers)</li>
|
||||
<li>PDF security tools (watermark, protect, unlock)</li>
|
||||
<li>PDF/image conversion tools (PDF→Images, Images→PDF)</li>
|
||||
<li>Image processing tools (convert, resize)</li>
|
||||
<li>Video to GIF tool</li>
|
||||
<li>Text tools (word counter, cleaner)</li>
|
||||
<li>PDF to flowchart extraction tool</li>
|
||||
</ul>
|
||||
{/* Security */}
|
||||
<section className="mb-10">
|
||||
<div className="flex items-center gap-3 mb-3">
|
||||
<Shield className="h-6 w-6 text-primary-600 dark:text-primary-400" />
|
||||
<h2 className="text-xl font-semibold text-slate-900 dark:text-white">
|
||||
{t('pages.about.securityTitle')}
|
||||
</h2>
|
||||
</div>
|
||||
<p className="text-slate-600 dark:text-slate-400 leading-relaxed">
|
||||
{t('pages.about.securityText')}
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<h2>Contact</h2>
|
||||
<p>
|
||||
Have feedback or feature requests? Reach out at{' '}
|
||||
<a href="mailto:support@example.com">support@example.com</a>.
|
||||
</p>
|
||||
{/* File Privacy */}
|
||||
<section className="mb-10">
|
||||
<div className="flex items-center gap-3 mb-3">
|
||||
<Lock className="h-6 w-6 text-primary-600 dark:text-primary-400" />
|
||||
<h2 className="text-xl font-semibold text-slate-900 dark:text-white">
|
||||
{t('pages.about.privacyTitle')}
|
||||
</h2>
|
||||
</div>
|
||||
<p className="text-slate-600 dark:text-slate-400 leading-relaxed">
|
||||
{t('pages.about.privacyText', { minutes: FILE_RETENTION_MINUTES })}
|
||||
</p>
|
||||
</section>
|
||||
|
||||
{/* What We Offer */}
|
||||
<section className="mb-10">
|
||||
<div className="flex items-center gap-3 mb-3">
|
||||
<Wrench className="h-6 w-6 text-primary-600 dark:text-primary-400" />
|
||||
<h2 className="text-xl font-semibold text-slate-900 dark:text-white">
|
||||
{t('pages.about.toolsTitle')}
|
||||
</h2>
|
||||
</div>
|
||||
{Array.isArray(toolCategories) && (
|
||||
<ul className="list-disc space-y-2 pl-5 text-slate-600 dark:text-slate-400">
|
||||
{toolCategories.map((cat, idx) => (
|
||||
<li key={idx}>{cat}</li>
|
||||
))}
|
||||
</ul>
|
||||
)}
|
||||
</section>
|
||||
|
||||
{/* CTA */}
|
||||
<div className="rounded-xl border border-slate-200 bg-white p-6 text-center dark:border-slate-700 dark:bg-slate-800">
|
||||
<p className="mb-4 text-slate-600 dark:text-slate-400">
|
||||
<Link to="/contact" className="font-medium text-primary-600 hover:text-primary-700 dark:text-primary-400 dark:hover:text-primary-300">
|
||||
{t('common.contact')}
|
||||
</Link>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
|
||||
179
frontend/src/pages/ContactPage.tsx
Normal file
179
frontend/src/pages/ContactPage.tsx
Normal file
@@ -0,0 +1,179 @@
|
||||
import { useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Helmet } from 'react-helmet-async';
|
||||
import { Mail, Send, CheckCircle } from 'lucide-react';
|
||||
|
||||
const CONTACT_EMAIL = 'support@saas-pdf.com';
|
||||
|
||||
type Category = 'general' | 'bug' | 'feature';
|
||||
|
||||
export default function ContactPage() {
|
||||
const { t } = useTranslation();
|
||||
const [category, setCategory] = useState<Category>('general');
|
||||
const [submitted, setSubmitted] = useState(false);
|
||||
|
||||
const placeholderKey = `pages.contact.${category}Placeholder` as const;
|
||||
|
||||
function handleSubmit(e: React.FormEvent<HTMLFormElement>) {
|
||||
e.preventDefault();
|
||||
const form = e.currentTarget;
|
||||
const data = new FormData(form);
|
||||
const subject = data.get('subject') as string;
|
||||
const body = data.get('message') as string;
|
||||
const name = data.get('name') as string;
|
||||
|
||||
// Open user's email client with pre-filled fields
|
||||
const mailto = `mailto:${CONTACT_EMAIL}?subject=${encodeURIComponent(`[${category}] ${subject}`)}&body=${encodeURIComponent(`From: ${name}\n\n${body}`)}`;
|
||||
window.location.href = mailto;
|
||||
setSubmitted(true);
|
||||
}
|
||||
|
||||
if (submitted) {
|
||||
return (
|
||||
<>
|
||||
<Helmet>
|
||||
<title>{t('pages.contact.title')} — {t('common.appName')}</title>
|
||||
</Helmet>
|
||||
<div className="mx-auto flex max-w-md flex-col items-center gap-4 py-20 text-center">
|
||||
<CheckCircle className="h-16 w-16 text-green-500" />
|
||||
<h2 className="text-2xl font-bold text-slate-800 dark:text-slate-100">
|
||||
{t('pages.contact.successMessage')}
|
||||
</h2>
|
||||
<button
|
||||
onClick={() => setSubmitted(false)}
|
||||
className="mt-4 rounded-lg bg-primary-600 px-6 py-2 text-white transition-colors hover:bg-primary-700"
|
||||
>
|
||||
{t('pages.contact.title')}
|
||||
</button>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<Helmet>
|
||||
<title>{t('pages.contact.title')} — {t('common.appName')}</title>
|
||||
<meta name="description" content={t('pages.contact.metaDescription')} />
|
||||
<link rel="canonical" href={`${window.location.origin}/contact`} />
|
||||
</Helmet>
|
||||
|
||||
<div className="mx-auto max-w-2xl">
|
||||
<div className="mb-8 text-center">
|
||||
<h1 className="text-3xl font-bold text-slate-800 dark:text-slate-100">
|
||||
{t('pages.contact.title')}
|
||||
</h1>
|
||||
<p className="mt-2 text-slate-600 dark:text-slate-400">
|
||||
{t('pages.contact.subtitle')}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<form onSubmit={handleSubmit} className="space-y-6 rounded-xl border border-slate-200 bg-white p-6 shadow-sm dark:border-slate-700 dark:bg-slate-800">
|
||||
<h2 className="text-lg font-semibold text-slate-700 dark:text-slate-200">
|
||||
{t('pages.contact.formTitle')}
|
||||
</h2>
|
||||
|
||||
{/* Category */}
|
||||
<div>
|
||||
<label className="mb-1 block text-sm font-medium text-slate-700 dark:text-slate-300">
|
||||
{t('pages.contact.categoryLabel')}
|
||||
</label>
|
||||
<select
|
||||
value={category}
|
||||
onChange={(e) => setCategory(e.target.value as Category)}
|
||||
className="w-full rounded-lg border border-slate-300 bg-white px-4 py-2 text-slate-700 focus:border-primary-500 focus:outline-none focus:ring-2 focus:ring-primary-200 dark:border-slate-600 dark:bg-slate-700 dark:text-slate-200"
|
||||
>
|
||||
<option value="general">{t('pages.contact.categories.general')}</option>
|
||||
<option value="bug">{t('pages.contact.categories.bug')}</option>
|
||||
<option value="feature">{t('pages.contact.categories.feature')}</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
{/* Name */}
|
||||
<div>
|
||||
<label htmlFor="name" className="mb-1 block text-sm font-medium text-slate-700 dark:text-slate-300">
|
||||
{t('common.name')}
|
||||
</label>
|
||||
<input
|
||||
id="name"
|
||||
name="name"
|
||||
type="text"
|
||||
required
|
||||
placeholder={t('pages.contact.namePlaceholder')}
|
||||
className="w-full rounded-lg border border-slate-300 bg-white px-4 py-2 text-slate-700 focus:border-primary-500 focus:outline-none focus:ring-2 focus:ring-primary-200 dark:border-slate-600 dark:bg-slate-700 dark:text-slate-200"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Email */}
|
||||
<div>
|
||||
<label htmlFor="email" className="mb-1 block text-sm font-medium text-slate-700 dark:text-slate-300">
|
||||
{t('common.email')}
|
||||
</label>
|
||||
<input
|
||||
id="email"
|
||||
name="email"
|
||||
type="email"
|
||||
required
|
||||
placeholder={t('pages.contact.emailPlaceholder')}
|
||||
className="w-full rounded-lg border border-slate-300 bg-white px-4 py-2 text-slate-700 focus:border-primary-500 focus:outline-none focus:ring-2 focus:ring-primary-200 dark:border-slate-600 dark:bg-slate-700 dark:text-slate-200"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Subject */}
|
||||
<div>
|
||||
<label htmlFor="subject" className="mb-1 block text-sm font-medium text-slate-700 dark:text-slate-300">
|
||||
{t('common.subject')}
|
||||
</label>
|
||||
<input
|
||||
id="subject"
|
||||
name="subject"
|
||||
type="text"
|
||||
required
|
||||
placeholder={t('pages.contact.subjectPlaceholder')}
|
||||
className="w-full rounded-lg border border-slate-300 bg-white px-4 py-2 text-slate-700 focus:border-primary-500 focus:outline-none focus:ring-2 focus:ring-primary-200 dark:border-slate-600 dark:bg-slate-700 dark:text-slate-200"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Message */}
|
||||
<div>
|
||||
<label htmlFor="message" className="mb-1 block text-sm font-medium text-slate-700 dark:text-slate-300">
|
||||
{t('common.message')}
|
||||
</label>
|
||||
<textarea
|
||||
id="message"
|
||||
name="message"
|
||||
rows={6}
|
||||
required
|
||||
placeholder={t(placeholderKey)}
|
||||
className="w-full rounded-lg border border-slate-300 bg-white px-4 py-2 text-slate-700 focus:border-primary-500 focus:outline-none focus:ring-2 focus:ring-primary-200 dark:border-slate-600 dark:bg-slate-700 dark:text-slate-200"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Submit */}
|
||||
<button
|
||||
type="submit"
|
||||
className="flex w-full items-center justify-center gap-2 rounded-lg bg-primary-600 px-6 py-3 font-medium text-white transition-colors hover:bg-primary-700"
|
||||
>
|
||||
<Send className="h-4 w-4" />
|
||||
{t('common.send')}
|
||||
</button>
|
||||
</form>
|
||||
|
||||
{/* Direct email fallback */}
|
||||
<div className="mt-6 text-center text-sm text-slate-500 dark:text-slate-400">
|
||||
<p>
|
||||
{t('pages.contact.directEmail')}{' '}
|
||||
<a
|
||||
href={`mailto:${CONTACT_EMAIL}`}
|
||||
className="inline-flex items-center gap-1 font-medium text-primary-600 hover:underline dark:text-primary-400"
|
||||
>
|
||||
<Mail className="h-4 w-4" />
|
||||
{CONTACT_EMAIL}
|
||||
</a>
|
||||
</p>
|
||||
<p className="mt-1">{t('pages.contact.responseTime')}</p>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -3,58 +3,55 @@ import { Helmet } from 'react-helmet-async';
|
||||
import { FILE_RETENTION_MINUTES } from '@/config/toolLimits';
|
||||
|
||||
const LAST_UPDATED = '2026-03-06';
|
||||
const CONTACT_EMAIL = 'support@saas-pdf.com';
|
||||
|
||||
export default function PrivacyPage() {
|
||||
const { t } = useTranslation();
|
||||
const fileItems = t('pages.privacy.fileHandlingItems', { minutes: FILE_RETENTION_MINUTES, returnObjects: true }) as string[];
|
||||
const thirdPartyItems = t('pages.privacy.thirdPartyItems', { returnObjects: true }) as string[];
|
||||
|
||||
return (
|
||||
<>
|
||||
<Helmet>
|
||||
<title>{t('common.privacy')} — {t('common.appName')}</title>
|
||||
<meta name="description" content="Privacy policy for our online tools." />
|
||||
<title>{t('pages.privacy.title')} — {t('common.appName')}</title>
|
||||
<meta name="description" content={t('pages.privacy.metaDescription')} />
|
||||
<link rel="canonical" href={`${window.location.origin}/privacy`} />
|
||||
</Helmet>
|
||||
|
||||
<div className="prose mx-auto max-w-2xl dark:prose-invert">
|
||||
<h1>{t('common.privacy')}</h1>
|
||||
<p><em>Last updated: {LAST_UPDATED}</em></p>
|
||||
<h1>{t('pages.privacy.title')}</h1>
|
||||
<p><em>{t('pages.privacy.lastUpdated', { date: LAST_UPDATED })}</em></p>
|
||||
|
||||
<h2>1. Data Collection</h2>
|
||||
<h2>{t('pages.privacy.dataCollectionTitle')}</h2>
|
||||
<p>{t('pages.privacy.dataCollectionText')}</p>
|
||||
|
||||
<h2>{t('pages.privacy.fileHandlingTitle')}</h2>
|
||||
{Array.isArray(fileItems) && (
|
||||
<ul>
|
||||
{fileItems.map((item, idx) => <li key={idx}>{item}</li>)}
|
||||
</ul>
|
||||
)}
|
||||
|
||||
<h2>{t('pages.privacy.cookiesTitle')}</h2>
|
||||
<p>{t('pages.privacy.cookiesText')}</p>
|
||||
|
||||
<h2>{t('pages.privacy.thirdPartyTitle')}</h2>
|
||||
{Array.isArray(thirdPartyItems) && (
|
||||
<ul>
|
||||
{thirdPartyItems.map((item, idx) => <li key={idx}>{item}</li>)}
|
||||
</ul>
|
||||
)}
|
||||
|
||||
<h2>{t('pages.privacy.securityTitle')}</h2>
|
||||
<p>{t('pages.privacy.securityText')}</p>
|
||||
|
||||
<h2>{t('pages.privacy.rightsTitle')}</h2>
|
||||
<p>{t('pages.privacy.rightsText', { minutes: FILE_RETENTION_MINUTES })}</p>
|
||||
|
||||
<h2>{t('pages.privacy.contactTitle')}</h2>
|
||||
<p>
|
||||
We only collect files you intentionally upload for processing. We do not
|
||||
require registration, and we do not store personal information.
|
||||
</p>
|
||||
|
||||
<h2>2. File Processing & Storage</h2>
|
||||
<ul>
|
||||
<li>Uploaded files are processed on our secure servers.</li>
|
||||
<li>All uploaded and output files are <strong>automatically deleted within {FILE_RETENTION_MINUTES} minutes</strong>.</li>
|
||||
<li>Files are stored in encrypted cloud storage during processing.</li>
|
||||
<li>We do not access, read, or share the content of your files.</li>
|
||||
</ul>
|
||||
|
||||
<h2>3. Cookies & Analytics</h2>
|
||||
<p>
|
||||
We use essential cookies to remember your language preference. We may use
|
||||
Google Analytics and Google AdSense, which may place their own cookies.
|
||||
You can manage cookie preferences in your browser settings.
|
||||
</p>
|
||||
|
||||
<h2>4. Third-Party Services</h2>
|
||||
<ul>
|
||||
<li><strong>Google AdSense</strong> — for displaying advertisements.</li>
|
||||
<li><strong>AWS S3</strong> — for temporary file storage.</li>
|
||||
</ul>
|
||||
|
||||
<h2>5. Security</h2>
|
||||
<p>
|
||||
We employ industry-standard security measures including HTTPS encryption,
|
||||
file validation, rate limiting, and automatic file cleanup.
|
||||
</p>
|
||||
|
||||
<h2>6. Contact</h2>
|
||||
<p>
|
||||
Questions about this policy? Contact us at{' '}
|
||||
<a href="mailto:support@example.com">support@example.com</a>.
|
||||
{t('pages.privacy.contactText')}{' '}
|
||||
<a href={`mailto:${CONTACT_EMAIL}`}>{CONTACT_EMAIL}</a>.
|
||||
</p>
|
||||
</div>
|
||||
</>
|
||||
|
||||
@@ -3,65 +3,58 @@ import { Helmet } from 'react-helmet-async';
|
||||
import { FILE_RETENTION_MINUTES } from '@/config/toolLimits';
|
||||
|
||||
const LAST_UPDATED = '2026-03-06';
|
||||
const CONTACT_EMAIL = 'support@saas-pdf.com';
|
||||
|
||||
export default function TermsPage() {
|
||||
const { t } = useTranslation();
|
||||
const useItems = t('pages.terms.useItems', { returnObjects: true }) as string[];
|
||||
const fileItems = t('pages.terms.fileItems', { minutes: FILE_RETENTION_MINUTES, returnObjects: true }) as string[];
|
||||
|
||||
return (
|
||||
<>
|
||||
<Helmet>
|
||||
<title>{t('common.terms')} — {t('common.appName')}</title>
|
||||
<meta name="description" content="Terms of service for our online tools." />
|
||||
<title>{t('pages.terms.title')} — {t('common.appName')}</title>
|
||||
<meta name="description" content={t('pages.terms.metaDescription')} />
|
||||
<link rel="canonical" href={`${window.location.origin}/terms`} />
|
||||
</Helmet>
|
||||
|
||||
<div className="prose mx-auto max-w-2xl dark:prose-invert">
|
||||
<h1>{t('common.terms')}</h1>
|
||||
<p><em>Last updated: {LAST_UPDATED}</em></p>
|
||||
<h1>{t('pages.terms.title')}</h1>
|
||||
<p><em>{t('pages.terms.lastUpdated', { date: LAST_UPDATED })}</em></p>
|
||||
|
||||
<h2>1. Acceptance of Terms</h2>
|
||||
<h2>{t('pages.terms.acceptanceTitle')}</h2>
|
||||
<p>{t('pages.terms.acceptanceText')}</p>
|
||||
|
||||
<h2>{t('pages.terms.serviceTitle')}</h2>
|
||||
<p>{t('pages.terms.serviceText')}</p>
|
||||
|
||||
<h2>{t('pages.terms.useTitle')}</h2>
|
||||
{Array.isArray(useItems) && (
|
||||
<ul>
|
||||
{useItems.map((item, idx) => <li key={idx}>{item}</li>)}
|
||||
</ul>
|
||||
)}
|
||||
|
||||
<h2>{t('pages.terms.fileTitle')}</h2>
|
||||
{Array.isArray(fileItems) && (
|
||||
<ul>
|
||||
{fileItems.map((item, idx) => <li key={idx}>{item}</li>)}
|
||||
</ul>
|
||||
)}
|
||||
|
||||
<h2>{t('pages.terms.liabilityTitle')}</h2>
|
||||
<p>{t('pages.terms.liabilityText')}</p>
|
||||
|
||||
<h2>{t('pages.terms.ipTitle')}</h2>
|
||||
<p>{t('pages.terms.ipText')}</p>
|
||||
|
||||
<h2>{t('pages.terms.changesTitle')}</h2>
|
||||
<p>{t('pages.terms.changesText')}</p>
|
||||
|
||||
<h2>{t('pages.terms.contactTitle')}</h2>
|
||||
<p>
|
||||
By accessing and using SaaS-PDF, you agree to be bound by these Terms of
|
||||
Service. If you do not agree, please discontinue use immediately.
|
||||
</p>
|
||||
|
||||
<h2>2. Service Description</h2>
|
||||
<p>
|
||||
SaaS-PDF provides free online tools for file conversion, compression,
|
||||
and transformation. The service is provided “as is” without
|
||||
warranties of any kind.
|
||||
</p>
|
||||
|
||||
<h2>3. Acceptable Use</h2>
|
||||
<ul>
|
||||
<li>You may only upload files that you have the right to process.</li>
|
||||
<li>You must not upload malicious, illegal, or copyrighted content without authorization.</li>
|
||||
<li>Automated or excessive use of the service is prohibited.</li>
|
||||
</ul>
|
||||
|
||||
<h2>4. File Handling</h2>
|
||||
<ul>
|
||||
<li>All uploaded and processed files are automatically deleted within {FILE_RETENTION_MINUTES} minutes.</li>
|
||||
<li>We are not responsible for any data loss during processing.</li>
|
||||
<li>You are responsible for maintaining your own file backups.</li>
|
||||
</ul>
|
||||
|
||||
<h2>5. Limitation of Liability</h2>
|
||||
<p>
|
||||
SaaS-PDF shall not be liable for any direct, indirect, incidental, or
|
||||
consequential damages resulting from the use or inability to use the
|
||||
service.
|
||||
</p>
|
||||
|
||||
<h2>6. Changes to Terms</h2>
|
||||
<p>
|
||||
We reserve the right to modify these terms at any time. Continued use of
|
||||
the service after changes constitutes acceptance of the updated terms.
|
||||
</p>
|
||||
|
||||
<h2>7. Contact</h2>
|
||||
<p>
|
||||
Questions about these terms? Contact us at{' '}
|
||||
<a href="mailto:support@example.com">support@example.com</a>.
|
||||
{t('pages.terms.contactText')}{' '}
|
||||
<a href={`mailto:${CONTACT_EMAIL}`}>{CONTACT_EMAIL}</a>.
|
||||
</p>
|
||||
</div>
|
||||
</>
|
||||
|
||||
Reference in New Issue
Block a user