Skip to content

Commit 1720cc0

Browse files
committed
feat: Add terms of service and privacy policy pages
1 parent 281cef3 commit 1720cc0

File tree

8 files changed

+350
-91
lines changed

8 files changed

+350
-91
lines changed
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
{
2+
"privacy_policy": {
3+
"title": "Privacy Policy",
4+
"subtitle": "Your privacy is important to us. This Privacy Policy explains how we collect, use, disclose, and safeguard your information when you use our platform."
5+
},
6+
"privacy_policy_paragraphs": {
7+
"01": {
8+
"title": "Introduction",
9+
"content": [
10+
"React ChatBotify Gallery (\"we\", \"our\", \"us\") values your privacy. This Privacy Policy explains how we collect, use, disclose, and safeguard your information when you use our platform.",
11+
"By accessing or using React ChatBotify Gallery, you agree to the terms of this Privacy Policy."
12+
]
13+
},
14+
"02": {
15+
"title": "Information We Collect",
16+
"content": [
17+
"OAuth Account Information: When you log in to React ChatBotify Gallery via third-party OAuth providers like GitHub or Google, we collect and store basic information provided by these services, such as your email address and username. We do not store or manage user passwords and rely solely on third-party OAuth providers for authentication.",
18+
"User Associations: We maintain a simple table that associates users with their linked OAuth accounts. This information is used to manage your access to the platform and ensure that you can access your own themes and plugins.",
19+
"Themes and Plugins Ownership: We store information about the themes and plugins you upload to the platform, including ownership details.",
20+
"Favorites: We store information about the themes and plugins that you have favorited, allowing you to easily access and manage your preferred items."
21+
]
22+
},
23+
"03": {
24+
"title": "How We Use Your Information",
25+
"content": [
26+
"To Provide and Manage the Service: We use the information to manage your account, facilitate your access to the platform, and ensure that you can manage your themes, plugins, and favorites.",
27+
"Improve Our Service: We may use aggregated and anonymized data to understand how users interact with the platform and to improve our services.",
28+
"Communication: We may use your email address to communicate with you about updates, changes to the service, or important notices."
29+
]
30+
},
31+
"04": {
32+
"title": "Disclosure of Your Information",
33+
"content": [
34+
"Third-Party Service Providers: We may share your information with third-party service providers that assist us in providing the platform, such as hosting providers. These providers are obligated to protect your information and only use it for the purposes we specify.",
35+
"Legal Requirements: We may disclose your information if required by law or in response to valid requests by public authorities (e.g., a court or government agency)."
36+
]
37+
},
38+
"05": {
39+
"title": "Security of Your Information",
40+
"content": [
41+
"We take reasonable measures to protect the security of your information. However, no method of transmission over the internet or electronic storage is 100% secure.",
42+
"While we strive to use commercially acceptable means to protect your personal information, we cannot guarantee its absolute security."
43+
]
44+
},
45+
"06": {
46+
"title": "Data Retention",
47+
"content": [
48+
"We will retain your information for as long as your account is active or as needed to provide you with our services.",
49+
"We may also retain and use your information to comply with legal obligations, resolve disputes, and enforce our agreements."
50+
]
51+
},
52+
"07": {
53+
"title": "Your Rights",
54+
"content": [
55+
"Access and Correction: You have the right to access and correct your personal information. You can do this through your account settings or by contacting us directly.",
56+
"Account Deletion: You can request the deletion of your account and associated data by contacting us. Please note that some information may be retained for legal or administrative purposes."
57+
]
58+
},
59+
"08": {
60+
"title": "International Data Transfers",
61+
"content": [
62+
"Your information may be transferred to and maintained on servers located outside of your state, province, country, or other governmental jurisdiction where the data protection laws may differ from those of your jurisdiction.",
63+
"By using our service, you consent to such transfers."
64+
]
65+
},
66+
"09": {
67+
"title": "Changes to This Privacy Policy",
68+
"content": [
69+
"We may update our Privacy Policy from time to time.",
70+
"We will notify you of any changes by posting the new Privacy Policy on this page.",
71+
"You are advised to review this Privacy Policy periodically for any changes.",
72+
"Changes to this Privacy Policy are effective when they are posted on this page.",
73+
"If you have any questions or concerns about this Privacy Policy, please contact us on Discord."
74+
]
75+
}
76+
}
77+
}

public/locales/en/pages/termofservice.json renamed to public/locales/en/pages/termsofservice.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
{
22
"terms_of_service": {
3+
"title": "Terms of Service",
4+
"subtitle": "While open source libraries encourage collaboration and accessibility, it's essential to ensure that users and contributors understand their rights and responsibilities. Our Terms of Service provide clear guidelines on usage, modification and distribution."
5+
},
6+
"terms_of_service_paragraphs": {
37
"01": {
48
"title": "Introduction",
59
"content": [

src/App.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,9 @@ import ErrorPage from './pages/Error';
1414
import HomePage from './pages/Home';
1515
import LoginProcessPage from './pages/LoginProcess';
1616
import PluginsPage from './pages/Plugins';
17+
import PrivacyPolicy from './pages/PrivacyPolicy';
1718
import TeamsPage from './pages/Teams';
18-
import TermsOfService from "./pages/TermofService";
19+
import TermsOfService from './pages/TermsOfService';
1920
import ThemesPage from './pages/Themes';
2021
import UserProfilePage from './pages/UserProfile';
2122
import ProtectedRoute from './routes/ProtectedRoute';
@@ -76,9 +77,10 @@ const App: React.FC = () => {
7677
children: [
7778
{ element: <HomePage />, path: '/' },
7879
{ element: <PluginsPage />, path: '/plugins' },
80+
{ element: <PrivacyPolicy />, path: '/privacy-policy' },
7981
{ element: <ThemesPage />, path: '/themes' },
8082
{ element: <TeamsPage />, path: '/teams' },
81-
{ element: <TermsOfService/>, path: '/terms-of-services' },
83+
{ element: <TermsOfService />, path: '/terms-of-service' },
8284
{
8385
element: <ProtectedRoute element={<UserProfilePage />} />,
8486
path: '/profile',

src/components/Home/Footer.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ const Footer = (): JSX.Element => {
5656
<Link sx={genericLinksStyles} href="/teams">
5757
{footerLinks[0].children[0]}
5858
</Link>
59-
<Link sx={genericLinksStyles} href="#">
59+
<Link sx={genericLinksStyles} href={Endpoints.gitHubCoreOrgSponsorUrl}>
6060
{footerLinks[0].children[1]}
6161
</Link>
6262
</Stack>
@@ -85,10 +85,10 @@ const Footer = (): JSX.Element => {
8585
<Typography fontWeight="bold" variant="h6">
8686
{footerLinks[2].title}
8787
</Typography>
88-
<Link sx={genericLinksStyles} href="#">
88+
<Link sx={genericLinksStyles} href="/terms-of-service">
8989
{footerLinks[2].children[0]}
9090
</Link>
91-
<Link sx={genericLinksStyles} href="#">
91+
<Link sx={genericLinksStyles} href="/privacy-policy">
9292
{footerLinks[2].children[1]}
9393
</Link>
9494
</Stack>

src/constants/Endpoints.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ const Endpoints = {
1313
fetchUserProfile: `${import.meta.env.VITE_GALLERY_API_URL}/api/v1/users/profile`,
1414
galleryAuthRedirectUrl: `${import.meta.env.VITE_GALLERY_API_URL}/api/v1/auth/callback`,
1515
gitHubCoreOrgUrl: 'https://github.com/React-ChatBotify',
16+
gitHubCoreOrgSponsorUrl: 'https://github.com/sponsors/React-ChatBotify',
1617
gitHubLoginUrl: 'https://github.com/login/oauth/authorize',
1718
instagramCoreUrl: 'https://www.instagram.com/react.chatbotify',
1819
loginUser: `${import.meta.env.VITE_GALLERY_API_URL}/api/v1/auth/login/process`,

src/pages/PrivacyPolicy.tsx

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
import { Box, Container, Typography } from '@mui/material';
2+
import React from 'react';
3+
import { useTranslation } from 'react-i18next';
4+
5+
import logo from '@/assets/images/logo.webp'; // Logo import
6+
import FadeInOnView from '@/components/FadeComponent/FadeInOnView';
7+
import Footer from '@/components/Home/Footer';
8+
9+
// Define types for the translation structure
10+
interface ContentItem {
11+
point?: string;
12+
text: string;
13+
}
14+
15+
interface Section {
16+
title: string;
17+
content: (string | ContentItem)[];
18+
}
19+
20+
interface PrivacyPolicyTranslation {
21+
[sectionKey: string]: Section; // Dynamic section keys with a Section value
22+
}
23+
24+
/**
25+
* Privacy Policy component that displays data collection, usage, and user rights.
26+
*/
27+
const PrivacyPolicy: React.FC = () => {
28+
// Use i18next to fetch translations dynamically
29+
const { t } = useTranslation('/pages/privacypolicy');
30+
31+
// Type assertion for the translation data
32+
const privacyPolicy = t('privacy_policy_paragraphs', { returnObjects: true }) as PrivacyPolicyTranslation;
33+
34+
// Sorting the section keys numerically
35+
const sortedKeys = Object.keys(privacyPolicy).sort((a, b) => a.localeCompare(b, undefined, { numeric: true }));
36+
37+
return (
38+
<Box
39+
sx={{
40+
backgroundColor: 'background.paper',
41+
color: 'text.primary',
42+
px: { sm: '10%', xs: 0 },
43+
}}
44+
>
45+
<Container
46+
maxWidth="md"
47+
sx={{
48+
pt: { xs: 12, sm: 11, md: 10 },
49+
pb: { xs: 4, sm: 6, md: 10 },
50+
}}
51+
>
52+
{/* Logo */}
53+
<FadeInOnView>
54+
<Box sx={{ display: 'flex', justifyContent: 'center', mb: 4 }}>
55+
<Box
56+
component="img"
57+
src={logo}
58+
alt="React ChatBotify Gallery Logo"
59+
sx={{
60+
height: { xs: '54px', sm: '96px', md: '128px', lg: '160px', xl: '192px' },
61+
}}
62+
/>
63+
</Box>
64+
65+
{/* Header */}
66+
<Box sx={{ textAlign: 'left' }}>
67+
<Typography variant="h3" color="text.primary" fontWeight="bold" gutterBottom>
68+
{t('privacy_policy.title')}
69+
</Typography>
70+
<Typography variant="h6" color="text.secondary" fontWeight="light" gutterBottom>
71+
{t('privacy_policy.subtitle')}
72+
</Typography>
73+
</Box>
74+
</FadeInOnView>
75+
76+
{/* Sections */}
77+
{sortedKeys.map((sectionKey) => {
78+
const section = privacyPolicy[sectionKey];
79+
if (!section) return null;
80+
const { title, content } = section;
81+
const sectionNumber = sectionKey.padStart(2, '0');
82+
83+
return (
84+
<FadeInOnView>
85+
<Box key={sectionKey} sx={{ mt: 5 }}>
86+
<Typography variant="h5" color="text.primary" fontWeight="bold">
87+
<Typography variant="h5" color="text.secondary" component="span">
88+
{sectionNumber}
89+
</Typography>{' '}
90+
{title}
91+
</Typography>
92+
93+
{/* Plain text paragraphs */}
94+
{(content.filter((item) => typeof item === 'string') as string[]).map((text, idx) => (
95+
<Typography key={`text-${idx}`} variant="body1" color="text.primary" sx={{ mt: 1, mb: 2 }}>
96+
{text}
97+
</Typography>
98+
))}
99+
100+
{/* Pointed items */}
101+
{(content.filter((item) => typeof item !== 'string') as ContentItem[]).map((item, idx) => (
102+
<Typography key={`point-${idx}`} variant="body1" color="text.primary" sx={{ mt: 1, mb: 2 }}>
103+
<strong>{item.point}</strong> {item.text}
104+
</Typography>
105+
))}
106+
</Box>
107+
</FadeInOnView>
108+
);
109+
})}
110+
111+
{/* Effective date */}
112+
<Box sx={{ mt: 5, opacity: 0.5 }}>
113+
<Typography variant="body2" color="text.primary">
114+
{t('Effective date for this policy: 2nd of March 2025')}
115+
</Typography>
116+
</Box>
117+
</Container>
118+
<Container
119+
maxWidth={false}
120+
disableGutters
121+
sx={{
122+
px: { sm: 6, xs: 2 },
123+
}}
124+
>
125+
<Footer />
126+
</Container>
127+
</Box>
128+
);
129+
};
130+
131+
export default PrivacyPolicy;

src/pages/TermofService.tsx

Lines changed: 0 additions & 86 deletions
This file was deleted.

0 commit comments

Comments
 (0)