diff --git a/src/app/(pages)/(main)/home/page.tsx b/src/app/(pages)/(main)/home/page.tsx index eb4b33cd..1592c036 100644 --- a/src/app/(pages)/(main)/home/page.tsx +++ b/src/app/(pages)/(main)/home/page.tsx @@ -26,10 +26,21 @@ import { useRouter } from 'next/navigation' const Home = () => { const router = useRouter() + + // Define an array of suggestions + const suggestions = [ + '¡Come más frutas y verduras!', + '¡Sal a dar un paseo!', + '¡Toma más agua!', + '¡Hoy practica Mindfullness por 10 minutos!', + '¡Recuerda dormir 7-8 horas diarias!', + ] + const [isOpen, setIsOpen] = useState(true) const [isOpen2, setIsOpen2] = useState(true) const [userData, setUserData] = useState(null) const [user, setUser] = useState(null) + const [randomSuggestion, setRandomSuggestion] = useState(suggestions[0]) const getData = async () => { try { @@ -84,26 +95,12 @@ const Home = () => { setIsOpen2(!isOpen2) } - // Define an array of suggestions - const suggestions = [ - '¡Come más frutas y verduras!', - '¡Sal a dar un paseo!', - '¡Toma más agua!', - '¡Hoy practica Mindfullness por 10 minutos!', - '¡Recuerda dormir 7-8 horas diarias!', - ] - // Function to generate a random suggestion const generateRandomSuggestion = () => { const randomIndex = Math.floor(Math.random() * suggestions.length) return suggestions[randomIndex] } - // State to hold the current random suggestion - const [randomSuggestion, setRandomSuggestion] = useState( - generateRandomSuggestion(), - ) - // Function to generate a new random suggestion const handleGenerateSuggestion = () => { const newRandomSuggestion = generateRandomSuggestion() @@ -129,7 +126,9 @@ const Home = () => { Recomendación del Día
-

{randomSuggestion}

+

+ {randomSuggestion && randomSuggestion} +

+ >
@@ -236,15 +228,26 @@ const Home = () => {

- Mi Dashboard de Salud + Dashboard

-
- +
+ +
+ - + +

+ Mi suscripción +

+
+
@@ -299,13 +302,13 @@ const Home = () => {
diff --git a/src/app/(pages)/(main)/home/subscription/page.tsx b/src/app/(pages)/(main)/home/subscription/page.tsx new file mode 100644 index 00000000..494f0bd5 --- /dev/null +++ b/src/app/(pages)/(main)/home/subscription/page.tsx @@ -0,0 +1,128 @@ +'use client' +import { Plan } from '@/src/data/datatypes/payment' +import { plans } from '@/src/data/plans' +import axios from 'axios' +import { NextPage } from 'next' +import { useRouter } from 'next/navigation' +import { useEffect, useState } from 'react' + +const PricingPage: NextPage = () => { + interface Subscription { + plan: string + status: string + end?: number + } + + const [subscription, setSubscription] = useState(null) + + const getSubscriptionData = async () => { + try { + const res = await axios.get('/api/subscription') + const data = res.data + if (data.message === 'No subscription') { + setSubscription(null) + } else { + setSubscription(data) + } + } catch (error) { + console.log(error) + } + } + + const formatExpirationDate = (date: number) => { + const dateObject = new Date(date * 1000) + const dateString = dateObject.toLocaleString() + const dateDay = dateString.split(',')[0] + return dateDay + } + + useEffect(() => { + getSubscriptionData() + }, []) + + return ( +
+
+ {!subscription && ( +

+ No tienes una suscripción activa +

+ )} + {subscription && ( +

+ Tienes una subscripción de {subscription.plan} +

+ )} + {subscription && + subscription?.status === 'trialing' && + subscription.end && ( + <> +

+ Actualmente te encuentras en modo de prueba, contrata un plan + para no perder el acceso a la aplicación +

+

+ Tu subscripción expira el{' '} + {formatExpirationDate(subscription.end)} +

+ + )} + +

+ Contrata una subscripción a Vita +

+
+ {plans.map((plan, index) => ( + + ))} +
+
+
+ ) +} + +const PlanCard: React.FC<{ plan: Plan }> = ({ plan }) => { + const router = useRouter() + + const processPayment = async () => { + try { + const res = await axios.post('/api/stripe/payment', { + priceId: plan.priceId, + allowTrial: plan.allowTrial, + }) + const data = res.data + router.push(data.url) + } catch (error) { + console.log(error) + } + } + + return ( +
+
+

{plan.name}

+

${plan.price}/mes

+
    + {plan.features.map((feature, index) => ( +
  • + {feature} +
  • + ))} +
+ {plan.name === 'Bienestar Plus' && ( +

Pruébalo gratis por 7 días

+ )} +
+
+ +
+
+ ) +} + +export default PricingPage diff --git a/src/app/(pages)/plan/page.tsx b/src/app/(pages)/plan/page.tsx index 169813fe..b93c6ef3 100644 --- a/src/app/(pages)/plan/page.tsx +++ b/src/app/(pages)/plan/page.tsx @@ -1,60 +1,10 @@ 'use client' +import { Plan } from '@/src/data/datatypes/payment' +import { plans } from '@/src/data/plans' import axios from 'axios' import { NextPage } from 'next' import { useRouter } from 'next/navigation' -interface Plan { - name: string - price: number - features: string[] - priceId: string - allowTrial: boolean -} - -const plans: Plan[] = [ - { - name: 'Bienestar Básico', - price: 199, - features: [ - '31 rutinas de ejercicio y 300 recetas de comida al mes.', - '90 detecciones de comida al mes.', - 'Metas de ejercicio, nutrición y sueño.', - 'Blog de salud generado por inteligencia artificial', - 'Red Social para compartir progreso y apoyar a otros.', - 'Perfil Médico', - ], - priceId: 'price_1PODCEA5dyQt5UTQT1A5yBVQ', - allowTrial: false, - }, - { - name: 'Bienestar Plus', - price: 299, - features: [ - '100 rutinas de ejercicio y 300 recetas de comida al mes.', - '300 detecciones de comida al mes.', - 'Todos los beneficios del plan básico', - 'Chatbot de salud en la app.', - 'Recordatorios automáticos en Whatsapp.', - 'Retos mensuales e insignias por logros.', - ], - priceId: 'price_1PODQFA5dyQt5UTQ9ejvVNjG', - allowTrial: true, - }, - { - name: 'Bienestar Total', - price: 699, - features: [ - '300 rutinas de ejercicio y 300 recetas de comida al mes.', - '1200 detecciones de comida al mes.', - 'Todos los beneficios del plan plus.', - 'Chatbot por Whatsapp.', - 'Acceso prioritario a las nuevas funciones en desarrollo.', - ], - priceId: 'price_1PODRUA5dyQt5UTQqsDYIfuQ', - allowTrial: false, - }, -] - const PricingPage: NextPage = () => { return (
diff --git a/src/app/api/subscription/route.tsx b/src/app/api/subscription/route.tsx new file mode 100644 index 00000000..162084fd --- /dev/null +++ b/src/app/api/subscription/route.tsx @@ -0,0 +1,53 @@ +import { NextResponse } from 'next/server' +import { db } from '@/src/db/drizzle' +import { user } from '@/src/db/schema/schema' +import { eq } from 'drizzle-orm' +import { getServerSession } from 'next-auth' +import { authOptions } from '@/src/lib/auth/authOptions' +import { stripe } from '@/src/lib/stripe/stripe' +import { plans } from '@/src/data/plans' + +export async function GET() { + const session = await getServerSession(authOptions) + if (!session) { + return NextResponse.json('Unauthorized', { status: 404 }) + } + + try { + const existingUser = await db + .select() + .from(user) + .where(eq(user.idUser, session.user?.id)) + .limit(1) + + //find stripe subscription + const subscriptionId = existingUser[0].membership + if (!subscriptionId) { + return NextResponse.json({ message: 'No subscription' }, { status: 200 }) + } + + const subscription = await stripe.subscriptions.retrieve(subscriptionId) + + if ( + subscription.status !== 'active' && + subscription.status !== 'trialing' + ) { + return NextResponse.json({ message: 'No subscription' }, { status: 200 }) + } + + const subscriptionData = subscription.items.data[0].price.id + const planType = plans.find((plan) => plan.priceId === subscriptionData) + + return NextResponse.json( + { + plan: planType?.name, + status: subscription.status, + end: subscription.trial_end, + }, + { status: 200 }, + ) + } catch (error) { + console.log(error) + return NextResponse.json('Error processing registration', { status: 400 }) + } +} diff --git a/src/components/landing/Landing_About.tsx b/src/components/landing/Landing_About.tsx index 579e009a..d1a67cb6 100644 --- a/src/components/landing/Landing_About.tsx +++ b/src/components/landing/Landing_About.tsx @@ -14,7 +14,7 @@ const About: React.FC = () => {
-

+

VITA es una aplicación para monitorear tu salud a todo momento y recibir asesoramiento a través de inteligencia artificial y expertos en la diff --git a/src/components/landing/unete.tsx b/src/components/landing/unete.tsx index 8c741382..31a51b28 100644 --- a/src/components/landing/unete.tsx +++ b/src/components/landing/unete.tsx @@ -18,7 +18,7 @@ const HomePage: React.FC = () => {

-

+

Y disfruta de todos los {' '} diff --git a/src/data/datatypes/payment.tsx b/src/data/datatypes/payment.tsx new file mode 100644 index 00000000..6441dc55 --- /dev/null +++ b/src/data/datatypes/payment.tsx @@ -0,0 +1,7 @@ +export interface Plan { + name: string + price: number + features: string[] + priceId: string + allowTrial: boolean +} diff --git a/src/data/plans.tsx b/src/data/plans.tsx new file mode 100644 index 00000000..db2b3622 --- /dev/null +++ b/src/data/plans.tsx @@ -0,0 +1,45 @@ +import { Plan } from './datatypes/payment' + +export const plans: Plan[] = [ + { + name: 'Bienestar Básico', + price: 199, + features: [ + '31 rutinas de ejercicio y 300 recetas de comida al mes.', + '90 detecciones de comida al mes.', + 'Metas de ejercicio, nutrición y sueño.', + 'Blog de salud generado por inteligencia artificial', + 'Red Social para compartir progreso y apoyar a otros.', + 'Perfil Médico', + ], + priceId: 'price_1PODCEA5dyQt5UTQT1A5yBVQ', + allowTrial: false, + }, + { + name: 'Bienestar Plus', + price: 299, + features: [ + '100 rutinas de ejercicio y 300 recetas de comida al mes.', + '300 detecciones de comida al mes.', + 'Todos los beneficios del plan básico', + 'Chatbot de salud en la app.', + 'Recordatorios automáticos en Whatsapp.', + 'Retos mensuales e insignias por logros.', + ], + priceId: 'price_1PODQFA5dyQt5UTQ9ejvVNjG', + allowTrial: true, + }, + { + name: 'Bienestar Total', + price: 699, + features: [ + '300 rutinas de ejercicio y 300 recetas de comida al mes.', + '1200 detecciones de comida al mes.', + 'Todos los beneficios del plan plus.', + 'Chatbot por Whatsapp.', + 'Acceso prioritario a las nuevas funciones en desarrollo.', + ], + priceId: 'price_1PODRUA5dyQt5UTQqsDYIfuQ', + allowTrial: false, + }, +]