diff --git a/.env.example b/.env.example
index 80fd7d72..ed218ea2 100644
--- a/.env.example
+++ b/.env.example
@@ -9,6 +9,5 @@ NEXT_PUBLIC_ATHLONIX_STORAGE_URL=
SUPABASE_DOMAIN=
ATHLONIX_API_URL=
NEXT_PUBLIC_API_URL=
-
STRIPE_API_KEY=sk_test_xxx
STRIPE_WEBHOOK_SECRET=whsec_xxx
diff --git a/apps/admin/Dockerfile b/apps/admin/Dockerfile
index 1d240bbc..1b93f633 100644
--- a/apps/admin/Dockerfile
+++ b/apps/admin/Dockerfile
@@ -41,7 +41,8 @@ ENV NEXT_PUBLIC_ATHLONIX_STORAGE_URL ${NEXT_PUBLIC_ATHLONIX_STORAGE_URL}
COPY --from=pruner --chown=node:node /app/out/full/ ./
RUN pnpm turbo run build --filter admin && \
- pnpm prune --prod
+ pnpm prune --prod && \
+ pnpm --filter admin deploy --prod --ignore-scripts ./out
FROM base AS dev
WORKDIR /app
diff --git a/apps/api/package.json b/apps/api/package.json
index 7b3cb7c6..47ddea0d 100644
--- a/apps/api/package.json
+++ b/apps/api/package.json
@@ -17,7 +17,7 @@
"dependencies": {
"@hono/node-server": "^1.11.2",
"@hono/swagger-ui": "^0.2.2",
- "@hono/zod-openapi": "0.14.1",
+ "@hono/zod-openapi": "0.14.2",
"@hono/zod-validator": "^0.2.2",
"@repo/types": "workspace:*",
"@supabase/supabase-js": "^2.43.4",
diff --git a/apps/client/Dockerfile b/apps/client/Dockerfile
index 22416d23..554e754f 100644
--- a/apps/client/Dockerfile
+++ b/apps/client/Dockerfile
@@ -41,7 +41,8 @@ ENV NEXT_PUBLIC_ATHLONIX_STORAGE_URL ${NEXT_PUBLIC_ATHLONIX_STORAGE_URL}
COPY --from=pruner --chown=node:node /app/out/full/ ./
RUN pnpm turbo run build --filter client && \
- pnpm prune --prod
+ pnpm prune --prod && \
+ pnpm --filter client deploy --prod --ignore-scripts ./out
FROM base AS dev
WORKDIR /app
diff --git a/apps/client/app/(auth)/(members)/members/layout.tsx b/apps/client/app/(auth)/(members)/members/layout.tsx
new file mode 100644
index 00000000..e38f2588
--- /dev/null
+++ b/apps/client/app/(auth)/(members)/members/layout.tsx
@@ -0,0 +1,75 @@
+import '@repo/ui/globals.css';
+import { FileSearch, Flame, Home, LineChart, MessageSquareMore, Trophy, Users } from 'lucide-react';
+import Link from 'next/link';
+
+export default function RootLayout({
+ children,
+}: {
+ children: React.ReactNode;
+}): JSX.Element {
+ return (
+
+
+
+
+
+
+
+
+ Escape membre Athlonix
+
+
+
+
+
+
+
+
{children}
+
+
+
+ );
+}
diff --git a/apps/client/app/(auth)/(members)/members/page.tsx b/apps/client/app/(auth)/(members)/members/page.tsx
new file mode 100644
index 00000000..dc6e7a6f
--- /dev/null
+++ b/apps/client/app/(auth)/(members)/members/page.tsx
@@ -0,0 +1,12 @@
+function Page(): JSX.Element {
+ return (
+
+
Bienvenue sur la page des membres
+ {
+ // todo: add content
+ }
+
+ );
+}
+
+export default Page;
diff --git a/apps/client/app/(withNavbar)/votes/page.tsx b/apps/client/app/(auth)/(members)/members/votes/page.tsx
similarity index 89%
rename from apps/client/app/(withNavbar)/votes/page.tsx
rename to apps/client/app/(auth)/(members)/members/votes/page.tsx
index 228b880f..71e3fbeb 100644
--- a/apps/client/app/(withNavbar)/votes/page.tsx
+++ b/apps/client/app/(auth)/(members)/members/votes/page.tsx
@@ -1,10 +1,12 @@
'use client';
import type { Vote } from '@/app/lib/type/Votes';
+import { type User, checkSubscription } from '@/app/lib/user/utils';
import { getAllVotes } from '@/app/lib/votes/utils';
import { Badge } from '@repo/ui/components/ui/badge';
import { Button } from '@repo/ui/components/ui/button';
import { Card } from '@repo/ui/components/ui/card';
import { Loader2 } from 'lucide-react';
+import { useRouter } from 'next/navigation';
import { useEffect, useState } from 'react';
const Icons = {
@@ -15,12 +17,21 @@ export default function ListVotes() {
const [votes, setVotes] = useState([]);
const [loading, setLoading] = useState(true);
const [filter, setFilter] = useState<'all' | 'ongoing' | 'finished' | 'not_started'>('all');
+ const [subscriptionChecked, setSubscriptionChecked] = useState(false);
+ const router = useRouter();
useEffect(() => {
async function fetchData() {
+ if (!subscriptionChecked) {
+ const user = JSON.parse(localStorage.getItem('user') as string) as User;
+ if (!checkSubscription(user)) {
+ return router.push('/');
+ }
+ setSubscriptionChecked(true);
+ }
try {
const result = await getAllVotes();
- setVotes(result);
+ setVotes(result.data);
setLoading(false);
} catch (error) {
setLoading(false);
@@ -28,7 +39,7 @@ export default function ListVotes() {
}
fetchData();
- }, []);
+ }, [subscriptionChecked, router]);
const filteredVotes = () => {
switch (filter) {
diff --git a/apps/client/app/lib/user/utils.ts b/apps/client/app/lib/user/utils.ts
index 288e0e2c..acf288c9 100644
--- a/apps/client/app/lib/user/utils.ts
+++ b/apps/client/app/lib/user/utils.ts
@@ -17,7 +17,7 @@ export async function getUserInfo(): Promise {
if (!response.ok) {
throw new Error('Failed to fetch user info');
}
- const user = await response.json();
+ const user = (await response.json()) as User;
localStorage.setItem('user', JSON.stringify(user));
return user;
}
diff --git a/apps/client/app/lib/votes/utils.ts b/apps/client/app/lib/votes/utils.ts
index 9b4a5e83..4f5ca1bd 100644
--- a/apps/client/app/lib/votes/utils.ts
+++ b/apps/client/app/lib/votes/utils.ts
@@ -1,6 +1,6 @@
import type { Vote } from '../type/Votes';
-export async function getAllVotes(): Promise {
+export async function getAllVotes(): Promise<{ data: Vote[]; count: number }> {
const API_URL = process.env.NEXT_PUBLIC_API_URL;
const response = await fetch(`${API_URL}/polls?all=true`, {
headers: { Authorization: `Bearer ${localStorage.getItem('access_token')}` },
diff --git a/apps/client/app/ui/NavBar.tsx b/apps/client/app/ui/NavBar.tsx
index a540ac53..3482caf5 100644
--- a/apps/client/app/ui/NavBar.tsx
+++ b/apps/client/app/ui/NavBar.tsx
@@ -6,7 +6,7 @@ import Image from 'next/image';
import Link from 'next/link';
import { useEffect, useState } from 'react';
import type React from 'react';
-import { getUserAvatar } from '../lib/user/utils';
+import { type User, checkSubscription, getUserAvatar } from '../lib/user/utils';
interface LinkProp {
name: string;
@@ -38,10 +38,14 @@ function LogoutUser() {
export const NavBar: React.FC = ({ links }) => {
const [isAuthenticated, setIsAuthenticated] = useState(false);
+ const [user, setUser] = useState();
useEffect(() => {
- const user = localStorage.getItem('user');
- setIsAuthenticated(user !== null);
+ const user = localStorage.getItem('user') as unknown as User;
+ setUser(user);
+ if (user) {
+ setIsAuthenticated(true);
+ }
}, []);
const navBarElements = links.map((link) => {
@@ -80,6 +84,11 @@ export const NavBar: React.FC = ({ links }) => {
{getUserAvatar()}
+ {user !== undefined && checkSubscription(user) && (
+
+ )}