Skip to content

Commit aa2517e

Browse files
committed
feat: terms and coditions and privacy
1 parent 9ba2148 commit aa2517e

File tree

5 files changed

+213
-38
lines changed

5 files changed

+213
-38
lines changed

src/components/modals/ShareEmailModal.tsx

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,15 @@ import { sendEmail } from '../../features/email/api/emailApi';
88
import { Email } from '../../types/emails';
99
import { Loader2 } from 'lucide-react';
1010
import { getVerbName } from '../../lib/utils/verbUtils';
11+
import PrivacyModal from './PrivacyModal';
1112

1213
const ShareEmailModal: React.FC<{ onClose: () => void }> = ({ onClose }) => {
1314
const { data } = useEntries();
1415
const { username, managerName, managerEmail } = data;
1516
const [isSending, setIsSending] = useState(false);
1617
const [sendError, setSendError] = useState<string | null>(null);
1718
const [sendSuccess, setSendSuccess] = useState(false);
19+
const [isPrivacyModalOpen, setIsPrivacyModalOpen] = useState(false);
1820

1921
// Only include public statements that are not resolved
2022
const publicStatements = data.entries.filter(
@@ -115,10 +117,12 @@ const ShareEmailModal: React.FC<{ onClose: () => void }> = ({ onClose }) => {
115117
};
116118

117119
return (
118-
<Dialog open onOpenChange={onClose}>
119-
<DialogContent
120-
headerTitle={`Sharing with ${managerName || 'your manager'}`}
121-
>
120+
<>
121+
{isPrivacyModalOpen && <PrivacyModal onClose={() => setIsPrivacyModalOpen(false)} />}
122+
<Dialog open onOpenChange={onClose}>
123+
<DialogContent
124+
headerTitle={`Sharing with ${managerName || 'your manager'}`}
125+
>
122126
<div
123127
className='relative rounded-md overflow-hidden'
124128
style={{
@@ -154,7 +158,7 @@ const ShareEmailModal: React.FC<{ onClose: () => void }> = ({ onClose }) => {
154158
</p>
155159
)}
156160
<div className="mt-3 p-2 bg-gray-50 rounded-md text-xs text-gray-600 border border-gray-200">
157-
<p>Only public statements will be shared. For details on how we process your data, see our <a href="#" className="text-brand-pink underline">Privacy Policy</a>.</p>
161+
<p>Only public statements will be shared. For details on how we process your data, see our <button onClick={() => setIsPrivacyModalOpen(true)} className="text-brand-pink underline">Privacy Policy</button>.</p>
158162
</div>
159163
</div>
160164

@@ -251,6 +255,7 @@ const ShareEmailModal: React.FC<{ onClose: () => void }> = ({ onClose }) => {
251255
</div>
252256
</DialogContent>
253257
</Dialog>
258+
</>
254259
);
255260
};
256261

Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
'use client';
2+
3+
import React from 'react';
4+
import { SimpleDialog as Dialog, SimpleDialogContent as DialogContent } from '../ui/simple-dialog';
5+
import { Button } from '../ui/button';
6+
import { X, FileText, Check, AlertTriangle, Scale } from 'lucide-react';
7+
8+
interface TermsModalProps {
9+
onClose: () => void;
10+
}
11+
12+
const TermsModal: React.FC<TermsModalProps> = ({ onClose }) => {
13+
// Handler for clicks outside the modal
14+
const handleOutsideClick = (e: React.MouseEvent<HTMLDivElement>) => {
15+
// Only close if the click was directly on the overlay (not on the modal content)
16+
if (e.target === e.currentTarget) {
17+
onClose();
18+
}
19+
};
20+
21+
return (
22+
<div
23+
className='fixed inset-0 z-50 flex items-center justify-center overflow-hidden bg-black/50'
24+
onClick={handleOutsideClick}
25+
>
26+
<div
27+
className='bg-white m-2 sm:m-5 max-w-2xl w-full rounded-lg p-0 overflow-hidden shadow-xl'
28+
onClick={(e) => e.stopPropagation()} // Prevent clicks inside from closing
29+
>
30+
<div className='bg-brand-pink p-2 flex items-center justify-between sm:rounded-t-lg'>
31+
<h2 className='text-xl font-semibold text-white flex items-center'>
32+
<FileText className="mr-2" size={20} />
33+
Terms of Use
34+
</h2>
35+
<button
36+
className='text-white focus:outline-none focus:ring-2 focus:ring-white rounded-sm'
37+
onClick={onClose}
38+
>
39+
<X size={24} />
40+
</button>
41+
</div>
42+
43+
<div
44+
className='relative overflow-auto max-h-[70vh]'
45+
style={{
46+
background: 'linear-gradient(135deg, #f5f7fa 0%, #f8f9fb 100%)',
47+
}}
48+
>
49+
<div className='p-4 sm:p-6'>
50+
<div className="space-y-6">
51+
{/* Introduction */}
52+
<section>
53+
<h3 className="text-lg font-semibold text-gray-800 mb-3">
54+
1. Introduction
55+
</h3>
56+
<div className="bg-white p-4 rounded-lg shadow-sm text-gray-700">
57+
<p className="mb-2">
58+
Welcome to Beacons ("Service"), a workplace passport application provided by LIFT. By using our Service, you agree to these Terms of Use. Please read them carefully.
59+
</p>
60+
<p>
61+
The Service allows you to create, maintain, and selectively share workplace statements about your preferences, needs, and working style with your line managers and employers.
62+
</p>
63+
</div>
64+
</section>
65+
66+
{/* User Accounts */}
67+
<section>
68+
<h3 className="text-lg font-semibold text-gray-800 mb-3">
69+
2. User Accounts
70+
</h3>
71+
<div className="bg-white p-4 rounded-lg shadow-sm text-gray-700">
72+
<p className="mb-2">
73+
Authentication is provided through a secure magic link system sent to your email address. You are responsible for:
74+
</p>
75+
<ul className="list-disc pl-5 space-y-1">
76+
<li>Maintaining the security of your email account</li>
77+
<li>Only using magic links sent directly to your email</li>
78+
<li>Notifying us of any unauthorized access</li>
79+
</ul>
80+
<p className="mt-2">
81+
If you register with a new email address, a new passport will be created that cannot be merged with existing data. This is intentional for data protection reasons.
82+
</p>
83+
</div>
84+
</section>
85+
86+
{/* Your Content */}
87+
<section>
88+
<h3 className="text-lg font-semibold flex items-center text-gray-800 mb-3">
89+
<Check className="mr-2 text-brand-pink" size={20} />
90+
3. Your Content
91+
</h3>
92+
<div className="bg-white p-4 rounded-lg shadow-sm text-gray-700">
93+
<p className="mb-2">
94+
You retain ownership of all content you create through our Service. By using Beacons, you:
95+
</p>
96+
<ul className="list-disc pl-5 space-y-1">
97+
<li>Are responsible for the accuracy of your statements</li>
98+
<li>Control which statements are marked as "public" and can be shared</li>
99+
<li>Decide when to share information with your line manager</li>
100+
<li>Can update or delete your content at any time</li>
101+
</ul>
102+
</div>
103+
</section>
104+
105+
{/* Acceptable Use */}
106+
<section>
107+
<h3 className="text-lg font-semibold flex items-center text-gray-800 mb-3">
108+
<AlertTriangle className="mr-2 text-brand-pink" size={20} />
109+
4. Acceptable Use
110+
</h3>
111+
<div className="bg-white p-4 rounded-lg shadow-sm text-gray-700">
112+
<p className="mb-2">
113+
You agree not to use Beacons to:
114+
</p>
115+
<ul className="list-disc pl-5 space-y-2">
116+
<li>Create or share statements that are harmful, offensive, or discriminatory</li>
117+
<li>Attempt to gain unauthorized access to other users' data</li>
118+
<li>Upload malicious code or attempt to compromise the service</li>
119+
<li>Impersonate others or provide false information</li>
120+
</ul>
121+
</div>
122+
</section>
123+
124+
{/* Legal Terms */}
125+
<section>
126+
<h3 className="text-lg font-semibold flex items-center text-gray-800 mb-3">
127+
<Scale className="mr-2 text-brand-pink" size={20} />
128+
5. Legal Terms
129+
</h3>
130+
<div className="bg-white p-4 rounded-lg shadow-sm text-gray-700">
131+
<p className="mb-2">
132+
<strong>Service Modifications:</strong> We may modify or discontinue the Service at any time with reasonable notice.
133+
</p>
134+
<p className="mb-2">
135+
<strong>Limitation of Liability:</strong> To the fullest extent permitted by law, LIFT shall not be liable for any indirect, incidental, special, consequential, or punitive damages.
136+
</p>
137+
<p>
138+
<strong>Governing Law:</strong> These Terms are governed by the laws of [Jurisdiction], without regard to its conflict of law principles.
139+
</p>
140+
</div>
141+
</section>
142+
</div>
143+
144+
<div className="mt-6 flex justify-center">
145+
<Button
146+
variant='outline'
147+
className='px-6'
148+
type='button'
149+
onClick={onClose}
150+
>
151+
<X size={16} className='mr-1.5' />
152+
Close
153+
</Button>
154+
</div>
155+
</div>
156+
</div>
157+
</div>
158+
</div>
159+
);
160+
};
161+
162+
export default TermsModal;

src/features/auth/components/LoginPage.tsx

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ import { Input } from '../../../components/ui/input';
88
import { Button } from '../../../components/ui/button';
99
import { handleMagicLinkVerification } from '../authUtils';
1010
import { Loader2 } from 'lucide-react';
11+
import PrivacyModal from '../../../components/modals/PrivacyModal';
12+
import TermsModal from '../../../components/modals/TermsModal';
1113

1214
interface LoginPageProps {
1315
onSubmit?: (
@@ -24,6 +26,8 @@ const LoginPage: React.FC<LoginPageProps> = ({ onSubmit }) => {
2426
const [managerName, setManagerName] = useState('');
2527
const [step, setStep] = useState<'authenticate' | 'profile'>('authenticate');
2628
const [verifying, setVerifying] = useState(false);
29+
const [isPrivacyModalOpen, setIsPrivacyModalOpen] = useState(false);
30+
const [isTermsModalOpen, setIsTermsModalOpen] = useState(false);
2731

2832
// Handle token verification on initial load and URL changes
2933
useEffect(() => {
@@ -118,6 +122,12 @@ const LoginPage: React.FC<LoginPageProps> = ({ onSubmit }) => {
118122
return (
119123
<div className='min-h-screen flex items-center justify-center p-4 bg-gray-50'>
120124
<div className='bg-white shadow-lg rounded-lg p-8 max-w-md w-full'>
125+
{isPrivacyModalOpen && (
126+
<PrivacyModal onClose={() => setIsPrivacyModalOpen(false)} />
127+
)}
128+
{isTermsModalOpen && (
129+
<TermsModal onClose={() => setIsTermsModalOpen(false)} />
130+
)}
121131
{step === 'authenticate' ? (
122132
<>
123133
<h1 className='text-3xl font-bold mb-6 text-center'>Welcome to Beacons</h1>
@@ -126,7 +136,7 @@ const LoginPage: React.FC<LoginPageProps> = ({ onSubmit }) => {
126136
</p>
127137
<div className="mb-4 p-3 bg-gray-50 rounded-md border border-gray-200 text-sm text-gray-600">
128138
<p className="mb-2">
129-
By signing in, you agree to our <a href="#" className="text-brand-pink underline">Privacy Policy</a> and <a href="#" className="text-brand-pink underline">Terms of Use</a>.
139+
By signing in, you agree to our <button onClick={() => setIsPrivacyModalOpen(true)} className="text-brand-pink underline">Privacy Policy</button> and <button onClick={() => setIsTermsModalOpen(true)} className="text-brand-pink underline">Terms of Use</button>.
130140
</p>
131141
<p>
132142
We collect and process your data to provide the Beacons service. You control what information is shared with your employer.

src/layouts/components/Header.tsx

Lines changed: 1 addition & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,11 @@ import React, { useState } from 'react';
33
import { useEntries } from '../../features/statements/hooks/useEntries';
44
import SmallCircularQuestionCounter from '../../components/ui/questionCounter/smallCircularQuestionCounter';
55
import UserDataModal from '../../components/modals/UserDataModal';
6-
import PrivacyModal from '../../components/modals/PrivacyModal';
7-
import { Shield } from 'lucide-react';
86
import { Tooltip, TooltipTrigger, TooltipContent } from '../../components/ui/better-tooltip';
97

108
const Header: React.FC = () => {
119
const { data } = useEntries();
1210
const [isDashboardOpen, setIsDashboardOpen] = useState(false);
13-
const [isPrivacyModalOpen, setIsPrivacyModalOpen] = useState(false);
1411

1512
// Debug output to make sure username is correct
1613
//console.log("Header rendering with username:", data.username);
@@ -20,32 +17,15 @@ const Header: React.FC = () => {
2017
console.log('Opening modal directly');
2118
setIsDashboardOpen(true);
2219
};
23-
24-
// Function to open the privacy modal
25-
const openPrivacyModal = () => {
26-
setIsPrivacyModalOpen(true);
27-
};
2820

2921
return (
3022
<header className='bg-brand-pink text-white p-4 shadow-md sticky top-0 z-50'>
3123
<div className='container mx-auto'>
3224
{/* Simplified header layout */}
3325
<div className='flex flex-wrap items-center justify-between'>
34-
{/* Left section: Logo and Privacy */}
26+
{/* Left section: Logo */}
3527
<div className='flex items-center'>
3628
<img src='/lift_logo.png' alt='Logo' className='h-8 sm:h-10 mr-2' />
37-
<Tooltip>
38-
<TooltipTrigger asChild>
39-
<button
40-
onClick={openPrivacyModal}
41-
className="ml-2 p-1 rounded-full hover:bg-pink-700 transition-colors"
42-
aria-label="Privacy Information"
43-
>
44-
<Shield size={16} />
45-
</button>
46-
</TooltipTrigger>
47-
<TooltipContent>Privacy Information</TooltipContent>
48-
</Tooltip>
4929
</div>
5030

5131
{/* Center section: Title */}
@@ -81,11 +61,6 @@ const Header: React.FC = () => {
8161
</div>
8262
</div>
8363
</div>
84-
85-
{/* Render the privacy modal when open */}
86-
{isPrivacyModalOpen && (
87-
<PrivacyModal onClose={() => setIsPrivacyModalOpen(false)} />
88-
)}
8964
</header>
9065
);
9166
};

src/layouts/components/MainPage.tsx

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
'use client';
22

3-
import React from 'react';
3+
import React, { useState } from 'react';
44
import {
55
Tooltip,
66
TooltipTrigger,
@@ -12,13 +12,17 @@ import { Button } from '../../components/ui/button';
1212
import { Plus, Mail } from 'lucide-react';
1313
import StatementWizard from '../../features/wizard/components/StatementWizard';
1414
import ShareEmailModal from '../../components/modals/ShareEmailModal';
15+
import PrivacyModal from '../../components/modals/PrivacyModal';
16+
import TermsModal from '../../components/modals/TermsModal';
1517
// import TestStatementButton from '../../components/debug/TestButton';
1618

1719
const MainPage: React.FC = () => {
1820
const { data } = useEntries();
1921
const { username, managerName, managerEmail, entries } = data;
20-
const [isWizardOpen, setIsWizardOpen] = React.useState(false);
21-
const [isShareModalOpen, setIsShareModalOpen] = React.useState(false);
22+
const [isWizardOpen, setIsWizardOpen] = useState(false);
23+
const [isShareModalOpen, setIsShareModalOpen] = useState(false);
24+
const [isPrivacyModalOpen, setIsPrivacyModalOpen] = useState(false);
25+
const [isTermsModalOpen, setIsTermsModalOpen] = useState(false);
2226

2327
// Determine if email button should be disabled:
2428
const hasManagerEmail = managerEmail && managerEmail.trim().length > 0;
@@ -70,9 +74,18 @@ const MainPage: React.FC = () => {
7074
<footer className="mt-auto pt-6 pb-4 bg-gray-50 border-t border-gray-200">
7175
<div className="container mx-auto px-4">
7276
<div className="flex flex-col sm:flex-row justify-center items-center text-xs text-gray-500 space-y-2 sm:space-y-0 sm:space-x-4">
73-
<a href="#" className="hover:text-brand-pink hover:underline">Privacy Policy</a>
74-
<a href="#" className="hover:text-brand-pink hover:underline">Terms of Use</a>
75-
<a href="#" className="hover:text-brand-pink hover:underline">Data Protection</a>
77+
<button
78+
onClick={() => setIsPrivacyModalOpen(true)}
79+
className="hover:text-brand-pink hover:underline"
80+
>
81+
Privacy Policy
82+
</button>
83+
<button
84+
onClick={() => setIsTermsModalOpen(true)}
85+
className="hover:text-brand-pink hover:underline"
86+
>
87+
Terms of Use
88+
</button>
7689
<span>© {new Date().getFullYear()} Beacons</span>
7790
</div>
7891
</div>
@@ -126,6 +139,16 @@ const MainPage: React.FC = () => {
126139
{isShareModalOpen && (
127140
<ShareEmailModal onClose={() => setIsShareModalOpen(false)} />
128141
)}
142+
143+
{/* Conditionally render the privacy modal */}
144+
{isPrivacyModalOpen && (
145+
<PrivacyModal onClose={() => setIsPrivacyModalOpen(false)} />
146+
)}
147+
148+
{/* Conditionally render the terms modal */}
149+
{isTermsModalOpen && (
150+
<TermsModal onClose={() => setIsTermsModalOpen(false)} />
151+
)}
129152
</main>
130153
);
131154
};

0 commit comments

Comments
 (0)