Skip to content

Commit

Permalink
feat: add privacy policy page
Browse files Browse the repository at this point in the history
  • Loading branch information
backrunner committed Aug 25, 2024
1 parent 9920156 commit 4cfc1dd
Show file tree
Hide file tree
Showing 7 changed files with 167 additions and 8 deletions.
6 changes: 6 additions & 0 deletions Roadmap.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@

## Planned Features

### v0.1.2

- [x] Add a privacy policy page.
- [x] Add a cookie agreement banner at the bottom of the page.
- [ ] Add an option to allow an alert will not show up in the future once user dismiss it.

### v0.2.0

- [ ] Allow to delete a notification in both desktop and mobile devices.
Expand Down
46 changes: 46 additions & 0 deletions src/components/common/CookiePrivacyBanner.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<script setup lang="ts">
import { ref, onMounted } from 'vue';
import { Button } from '@/components/ui/button';
const isVisible = ref(false);
onMounted(() => {
const hasAcceptedCookies = localStorage.getItem('cookiesAccepted');
if (!hasAcceptedCookies) {
setTimeout(() => {
isVisible.value = true;
}, 500);
}
});
const acceptCookies = () => {
localStorage.setItem('cookiesAccepted', 'true');
isVisible.value = false;
};
</script>

<template>
<Transition name="slide-up">
<div v-if="isVisible" class="fixed bottom-0 left-0 right-0 bg-background border-t border-border p-4 shadow-lg z-50">
<div class="container mx-auto flex flex-col sm:flex-row items-center justify-between">
<p class="text-sm text-muted-foreground mb-4 sm:mb-0 sm:mr-4">
We use cookies and device information to improve your experience. By continuing to use our site, you agree to
our
<a href="/privacy-policy" class="text-primary hover:underline">Privacy Policy</a>.
</p>
<Button @click="acceptCookies" variant="outline" size="sm"> Accept </Button>
</div>
</div>
</Transition>
</template>

<style scoped>
.slide-up-enter-active,
.slide-up-leave-active {
transition: transform 0.3s ease-out;
}
.slide-up-enter-from,
.slide-up-leave-to {
transform: translateY(100%);
}
</style>
16 changes: 15 additions & 1 deletion src/components/common/Header.astro
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ const isAllowedUser = session?.user?.email && allowedEmails.includes(session.use

<header class="bg-background border rounded-lg shadow-sm mt-4 mb-4">
<div class="container mx-auto px-6 py-3 flex items-center justify-between">
<div class="text font-semibold text-primary">AlphaPush</div>
<div class="text font-semibold text-primary cursor-pointer" id="logo">AlphaPush</div>
{
isAllowedUser ? (
<TopUser
Expand All @@ -36,6 +36,20 @@ const isAllowedUser = session?.user?.email && allowedEmails.includes(session.use
</div>
</header>

<script>
document.addEventListener('DOMContentLoaded', () => {
const logo = document.getElementById('logo');
if (logo) {
logo.addEventListener('click', () => {
const currentPath = window.location.pathname;
if (currentPath !== '/' && currentPath !== '/403') {
window.location.href = '/';
}
});
}
});
</script>

<script>
document.addEventListener('DOMContentLoaded', () => {
const topUser = document.querySelector('top-user');
Expand Down
4 changes: 2 additions & 2 deletions src/components/common/Page.astro
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ const session = await getSession(Astro.request);
const allowedEmails = import.meta.env.ALLOWED_EMAILS?.split(',').map((email: string) => email.trim()) || [];
const isAllowedUser = session?.user?.email && allowedEmails.includes(session.user.email);
const isLoggedIn = !!session?.user && isAllowedUser;
const userEmail = isAllowedUser ? (session?.user?.email || '') : '';
const userEmail = isAllowedUser ? session?.user?.email || '' : '';
// Get the user agent from the request headers
const userAgent = Astro.request.headers.get('user-agent') || '';
Expand Down Expand Up @@ -330,4 +330,4 @@ const isMobile = isMobileDevice(userAgent);
});
</script>
</body>
</html>
</html>
2 changes: 1 addition & 1 deletion src/pages/403.astro
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { Card, CardContent } from '@/components/ui/card';
<Card>
<CardContent class="flex flex-col items-center justify-center">
<h1 class="text font-bold mb-4">Access Denied</h1>
<p class="text mb-2">Sorry, you don't have permission to access the push service.</p>
<p class="text-sm mb-2">Sorry, you don't have permission to access the push service.</p>
</CardContent>
</Card>
</Page>
11 changes: 7 additions & 4 deletions src/pages/index.astro
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
---
import { getSession } from 'auth-astro/server';
import CookiePrivacyBanner from '@/components/common/CookiePrivacyBanner.vue';
import Page from '@/components/common/Page.astro';
import NotificationList from '@/components/notification/NotificationList.vue';
import { getSession } from 'auth-astro/server';
const session = await getSession(Astro.request);
let initialNotifications = [];
Expand All @@ -28,9 +30,9 @@ if (session?.user?.email) {
if (response.ok) {
const data = (await response.json()) as { notifications: any[]; totalPages: number; totalCount: number };
const highlightedNotificationId = Astro.url.searchParams.get('notificationId');
initialNotifications = data.notifications.map(notification => ({
initialNotifications = data.notifications.map((notification) => ({
...notification,
highlight: notification.id === highlightedNotificationId
highlight: notification.id === highlightedNotificationId,
}));
totalPages = data.totalPages;
} else {
Expand All @@ -46,4 +48,5 @@ if (session?.user?.email) {
initialNotifications={initialNotifications}
initialTotalPages={totalPages}
/>
</Page>
<CookiePrivacyBanner client:load />
</Page>
90 changes: 90 additions & 0 deletions src/pages/privacy-policy.astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
---
import { marked } from 'marked';
import Page from '@/components/common/Page.astro';
import { Card, CardContent } from '@/components/ui/card';
const privacyPolicyMarkdown = `
# Privacy Policy
## Introduction
Welcome to AlphaPush. We are committed to protecting your privacy and ensuring the security of your personal information. This Privacy Policy explains how we collect, use, and safeguard your data when you use our service.
## Information We Collect
### Device Information
We use Fingerprint.js to collect device information for the purpose of improving your experience and ensuring the security of our service. This information may include:
### Cookies
We use cookies to enhance your browsing experience and provide personalized features. Cookies are small text files stored on your device that help us recognize you and remember your preferences.
## How We Use Your Information
The information we collect is used solely for the following purposes:
1. To provide and maintain our service
2. To improve user experience
## Data Security
We take the security of your data seriously. All device information and other data collected are:
- Not shared with any third parties
- Not stored alongside sensitive data in our local databases
- Protected using industry-standard security measures
## Your Rights
You have the right to:
- Access the personal information we hold about you
- Request correction of any inaccurate information
- Request deletion of your data from our systems
## Changes to This Policy
We may update this Privacy Policy from time to time. We will notify you of any changes by posting the new Privacy Policy on this page.
`;
const content = marked(privacyPolicyMarkdown);
---

<Page title="Privacy Policy" description="Our commitment to protecting your privacy">
<Card class="max-w-4xl mx-auto">
<CardContent class="prose dark:prose-invert max-w-none pt-8 px-8 pb-10">
<div set:html={content} class="space-y-8" />
</CardContent>
</Card>
<p class="text-sm text-center mt-8 mb-10 text-gray-600 dark:text-gray-400">Last updated: 2024-08-25</p>
</Page>

<style is:global>
.prose h1 {
@apply text-xl font-bold mb-4 text-primary;
}
.prose h2 {
@apply text-lg font-semibold mt-4 mb-2 text-primary;
}
.prose h3 {
@apply text-base font-medium my-2;
}
.prose p {
@apply mb-2 leading-relaxed;
}
.prose ul {
@apply list-disc list-inside mb-2 pl-4;
}
.prose ol {
@apply list-decimal list-inside mb-2 pl-4;
}
.prose li {
@apply mb-2;
}
.prose a {
@apply text-blue-600 hover:underline dark:text-blue-400;
}
.prose strong {
@apply font-semibold;
}
</style>

0 comments on commit 4cfc1dd

Please sign in to comment.