Skip to content

Commit

Permalink
fix(build): fixed build error
Browse files Browse the repository at this point in the history
  • Loading branch information
WomB0ComB0 committed Sep 27, 2024
1 parent 7080028 commit d050256
Show file tree
Hide file tree
Showing 10 changed files with 92 additions and 69 deletions.
Empty file removed app/components/layout/Layout.tsx
Empty file.
36 changes: 18 additions & 18 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@
"@googlemaps/markerclusterer": "^2.5.3",
"@hookform/resolvers": "^3.9.0",
"@js-temporal/polyfill": "^0.4.4",
"@liveblocks/client": "^2.7.2",
"@liveblocks/node": "^2.7.2",
"@liveblocks/react": "^2.7.2",
"@liveblocks/client": "^2.8.0",
"@liveblocks/node": "^2.8.0",
"@liveblocks/react": "^2.8.0",
"@million/lint": "^0.0.73",
"@opentelemetry/api-logs": "^0.53.0",
"@opentelemetry/instrumentation": "^0.53.0",
Expand All @@ -36,13 +36,13 @@
"@radix-ui/react-slot": "^1.1.0",
"@radix-ui/react-tabs": "^1.1.0",
"@radix-ui/react-tooltip": "^1.1.2",
"@sentry/nextjs": "^8.0.0",
"@sentry/types": "^8.30.0",
"@sentry/nextjs": "^8.32.0",
"@sentry/types": "^8.32.0",
"@stripe/stripe-js": "^4.5.0",
"@svgr/webpack": "^8.1.0",
"@t3-oss/env-nextjs": "^0.11.1",
"@tanstack/react-query": "^5.17.19",
"@tanstack/react-query-devtools": "^5.17.19",
"@tanstack/react-query": "^5.56.2",
"@tanstack/react-query-devtools": "^5.58.0",
"@trpc/client": "^10.45.2",
"@trpc/next": "^10.45.2",
"@trpc/react-query": "^10.45.2",
Expand All @@ -60,24 +60,24 @@
"date-fns": "^4.1.0",
"firebase": "^10.13.2",
"firebase-admin": "^12.5.0",
"framer-motion": "^11.5.6",
"framer-motion": "^11.9.0",
"htmlparser2": "^9.1.0",
"jotai": "^2.10.0",
"jotai-effect": "^1.0.3",
"jotai-tanstack-query": "^0.8.8",
"kbar": "0.1.0-beta.45",
"lucide-react": "^0.445.0",
"lucide-react": "^0.446.0",
"million": "^3.1.11",
"mkdirp": "^3.0.1",
"next": "^14.1.0",
"next": "^14.2.13",
"next-compose-plugins": "^2.2.1",
"next-firebase-auth-edge": "^1.7.1",
"next-pwa": "^5.6.0",
"next-themes": "^0.3.0",
"nextjs-progressbar": "^0.0.16",
"node-fetch": "^3.3.2",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-hook-form": "^7.53.0",
"react-icons": "^5.3.0",
"server-only": "^0.0.1",
Expand All @@ -99,19 +99,19 @@
"@graphql-codegen/cli": "5.0.2",
"@graphql-codegen/typescript": "4.0.9",
"@graphql-codegen/typescript-operations": "^4.2.3",
"@next/bundle-analyzer": "^14.1.0",
"@next/bundle-analyzer": "^14.2.13",
"@octokit/graphql-schema": "^15.25.0",
"@playwright/test": "^1.47.2",
"@tailwindcss/typography": "^0.5.15",
"@testing-library/react": "^16.0.1",
"@types/bun": "1.1.10",
"@types/google.maps": "^3.58.0",
"@types/node": "^22.5.5",
"@types/react": "^18.2.0",
"@types/react-dom": "^18.2.0",
"@types/google.maps": "^3.58.1",
"@types/node": "^22.7.4",
"@types/react": "^18.3.10",
"@types/react-dom": "^18.3.0",
"cross-env": "^7.0.3",
"postcss": "^8.4.47",
"tailwindcss": "^3.4.12",
"tailwindcss": "^3.4.13",
"typescript": "^5.6.2"
},
"ct3aMetadata": {
Expand Down
Binary file added public/assets/images/screen-shot-narrow.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/assets/images/screen-shot-wide.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
76 changes: 42 additions & 34 deletions src/app/(routes)/hire/page.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
'use client'
'use client';

import React, { useState } from 'react'
import { motion } from 'framer-motion'
import Layout from '@/components/layout/Layout'
import { Button } from '@/components/ui/button'
import { Card, CardContent, CardFooter, CardHeader, CardTitle } from '@/components/ui/card'
import { ScrollArea } from '@/components/ui/scroll-area'
import { Check, Loader2, Star, Code, Rocket, Database, Cloud } from 'lucide-react'
import { toast } from 'sonner'
import Link from 'next/link'
import { loadStripe } from '@stripe/stripe-js'
import Layout from '@/components/layout/Layout';
import { Button } from '@/components/ui/button';
import { Card, CardContent, CardFooter, CardHeader, CardTitle } from '@/components/ui/card';
import { ScrollArea } from '@/components/ui/scroll-area';
import { loadStripe } from '@stripe/stripe-js';
import { motion } from 'framer-motion';
import { Check, Cloud, Code, Database, Loader2, Rocket, Star } from 'lucide-react';
import Link from 'next/link';
import React, { useState } from 'react';
import { toast } from 'sonner';

const stripePromise = loadStripe(process.env.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY!)
const stripePromise = loadStripe(process.env.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY!);

const tiers = [
{
Expand All @@ -25,7 +25,7 @@ const tiers = [
'Minor feature implementations (e.g., simple form or button)',
'Basic bug fixes (JavaScript, React, etc.)',
'Basic code review and feedback',
'Email support'
'Email support',
],
},
{
Expand All @@ -39,7 +39,7 @@ const tiers = [
'UI/UX enhancements',
'Database setup (e.g., MySQL, MongoDB)',
'Basic CI/CD pipeline setup (GitHub Actions, CircleCI)',
'Priority email and chat support'
'Priority email and chat support',
],
},
{
Expand All @@ -55,7 +55,7 @@ const tiers = [
'Comprehensive testing with Jest, PyTest, etc.',
'DevOps setup (Docker, CI/CD optimization)',
'Weekly progress meetings',
'24/7 support'
'24/7 support',
],
},
{
Expand All @@ -72,12 +72,16 @@ const tiers = [
'Advanced DevOps (monitoring, Prometheus, Grafana)',
'Comprehensive documentation and training',
'Dedicated 24/7 support',
'Bi-weekly strategy meetings'
'Bi-weekly strategy meetings',
],
},
];

const PricingTier = ({ tier, onCheckout, isLoading }: { tier: any, onCheckout: any, isLoading: any }) => (
const PricingTier = ({
tier,
onCheckout,
isLoading,
}: { tier: any; onCheckout: any; isLoading: any }) => (
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
Expand Down Expand Up @@ -118,48 +122,51 @@ const PricingTier = ({ tier, onCheckout, isLoading }: { tier: any, onCheckout: a
</CardFooter>
</Card>
</motion.div>
)
);

export default function HirePage() {
const [loading, setLoading] = useState(false)
const [loading, setLoading] = useState(false);

const handleCheckout = async (priceId: string) => {
setLoading(true)
setLoading(true);
try {
const response = await fetch('/api/v1/checkout', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ priceId }),
})
});

if (!response.ok) {
throw new Error('Network response was not ok')
throw new Error('Network response was not ok');
}

const { sessionId } = await response.json()
const stripe = await stripePromise
const { error } = await stripe!.redirectToCheckout({ sessionId })
const { sessionId } = await response.json();
const stripe = await stripePromise;
const { error } = await stripe!.redirectToCheckout({ sessionId });

if (error) {
console.error('Stripe checkout error:', error)
console.error('Stripe checkout error:', error);
}
} catch (error) {
console.error('Failed to create checkout session:', error)
toast.error('Failed to create checkout session. Please try again.')
console.error('Failed to create checkout session:', error);
toast.error('Failed to create checkout session. Please try again.');
} finally {
setLoading(false)
setLoading(false);
}
}
};

return (
<Layout>
<div className="py-16 px-4 sm:px-6 lg:px-8">
<div className="max-w-4xl mx-auto">
<h1 className="text-4xl sm:text-5xl font-extrabold mb-4 text-center ">Hire Me for Your Next Project</h1>
<h1 className="text-4xl sm:text-5xl font-extrabold mb-4 text-center ">
Hire Me for Your Next Project
</h1>
<p className="text-lg sm:text-xl text-center mb-12 max-w-3xl mx-auto">
With expertise in web, mobile, desktop, cloud, and game development, I can bring your vision to life. Choose the plan that fits your project's scope and complexity.
With expertise in web, mobile, desktop, cloud, and game development, I can bring your
vision to life. Choose the plan that fits your project's scope and complexity.
</p>
<div className="grid gap-8 sm:grid-cols-2">
{tiers.map((tier) => (
Expand All @@ -172,7 +179,8 @@ export default function HirePage() {
))}
</div>
<p className="text-center mt-12 text-purple-200">
Not sure which plan is right for you? <Link
Not sure which plan is right for you?{' '}
<Link
href="mailto:mikeodnis32420024@gmail.com"
className="text-purple-400 hover:underline"
>
Expand All @@ -183,5 +191,5 @@ export default function HirePage() {
</div>
</div>
</Layout>
)
);
}
5 changes: 4 additions & 1 deletion src/app/api/v1/checkout/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ export async function POST(request: Request) {
return NextResponse.json({ sessionId: session.id });
} catch (error) {
console.error('Error in checkout API route:', error);
return NextResponse.json({ error: 'Failed to create checkout session', details: (error as Error).message }, { status: 500 });
return NextResponse.json(
{ error: 'Failed to create checkout session', details: (error as Error).message },
{ status: 500 },
);
}
}
26 changes: 19 additions & 7 deletions src/app/api/webhook/admin.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
import type Stripe from 'stripe';
import { stripe } from '@/utils/stripe';
import type Stripe from 'stripe';
const upsertProductRecord = async (product: Stripe.Product) => {
// Here you would typically update your database with the product information
console.log(`Product ${product.id} ${product.active ? 'activated' : 'deactivated'}: ${product.name}`);
console.log(
`Product ${product.id} ${product.active ? 'activated' : 'deactivated'}: ${product.name}`,
);
};

const upsertPriceRecord = async (price: Stripe.Price) => {
// Here you would typically update your database with the price information
console.log(`Price ${price.id} for product ${price.product}: ${price.unit_amount} ${price.currency}`);
console.log(
`Price ${price.id} for product ${price.product}: ${price.unit_amount} ${price.currency}`,
);
};

const deleteProductRecord = async (product: Stripe.Product) => {
Expand All @@ -32,21 +36,29 @@ const createOrRetrieveCustomer = async ({ email, uuid }: { email: string; uuid:
const manageSubscriptionStatusChange = async (
subscriptionId: string,
customerId: string,
createAction = false
createAction = false,
) => {
const subscription = await stripe.subscriptions.retrieve(subscriptionId, {
expand: ['default_payment_method'],
});

// Here you would typically update your database with the subscription information
console.log(`Subscription ${subscription.id} for customer ${customerId} is ${subscription.status}`);
console.log(
`Subscription ${subscription.id} for customer ${customerId} is ${subscription.status}`,
);

if (createAction && subscription.default_payment_method) {
await copyBillingDetailsToCustomer(customerId, subscription.default_payment_method as Stripe.PaymentMethod);
await copyBillingDetailsToCustomer(
customerId,
subscription.default_payment_method as Stripe.PaymentMethod,
);
}
};

const copyBillingDetailsToCustomer = async (customerId: string, paymentMethod: Stripe.PaymentMethod) => {
const copyBillingDetailsToCustomer = async (
customerId: string,
paymentMethod: Stripe.PaymentMethod,
) => {
const { name, phone, address } = paymentMethod.billing_details;
if (!name || !phone || !address) return;

Expand Down
14 changes: 7 additions & 7 deletions src/app/api/webhook/route.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { NextResponse } from 'next/server';
import Stripe from 'stripe';
import {
upsertProductRecord,
upsertPriceRecord,
deleteProductRecord,
deletePriceRecord,
manageSubscriptionStatusChange
deleteProductRecord,
manageSubscriptionStatusChange,
upsertPriceRecord,
upsertProductRecord,
} from './admin';

const stripe = new Stripe(process.env.NEXT_PUBLIC_STRIPE_SECRET_KEY!, {
Expand Down Expand Up @@ -67,7 +67,7 @@ export async function POST(req: Request) {
await manageSubscriptionStatusChange(
subscription.id,
subscription.customer as string,
event.type === 'customer.subscription.created'
event.type === 'customer.subscription.created',
);
break;
case 'checkout.session.completed':
Expand All @@ -77,7 +77,7 @@ export async function POST(req: Request) {
await manageSubscriptionStatusChange(
subscriptionId,
checkoutSession.customer as string,
true
true,
);
}
break;
Expand All @@ -88,7 +88,7 @@ export async function POST(req: Request) {
console.error('Error handling webhook:', error);
return NextResponse.json(
{ error: 'Webhook handler failed. View your Next.js function logs.' },
{ status: 400 }
{ status: 400 },
);
}
} else {
Expand Down
2 changes: 1 addition & 1 deletion src/app/manifest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -817,7 +817,7 @@ export default function manifest(): ExtendedManifest {
name: 'Blog',
short_name: 'Blog',
url: '/blog',
description: 'Read Mike\'s latest thoughts and updates on his blog.',
description: "Read Mike's latest thoughts and updates on his blog.",
icons: [
{
src: '/assets/svgs/logo-small.svg',
Expand Down
2 changes: 1 addition & 1 deletion src/utils/stripe.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import Stripe from 'stripe';

if (!process.env.NEXT_PUBLIC_STRIPE_SECRET_KEY) {
throw new Error('STRIPE_SECRET_KEY is not set in the environment variables');
throw new Error('NEXT_PUBLIC_STRIPE_SECRET_KEY is not set in the environment variables');
}

export const stripe = new Stripe(process.env.NEXT_PUBLIC_STRIPE_SECRET_KEY, {
Expand Down

0 comments on commit d050256

Please sign in to comment.