Skip to content

Commit

Permalink
Stripe Integration (#451)
Browse files Browse the repository at this point in the history
* Core Stripe setup

* Webhooks and success/cancel pages

* Order model, crud, routers, and page

* Stripe env setup fixed and cleanup

* Rename stripe env vars to have vite_ prefix

* Webhooks, order creation and view flow

* Stripe env rename and add to github workflows

* Add order shipping address

* Stompy micro product, price no longer hard coded

* Fix lint
  • Loading branch information
Winston-Hsiao authored Oct 15, 2024
1 parent 66345b9 commit ad10447
Show file tree
Hide file tree
Showing 31 changed files with 1,461 additions and 25 deletions.
1 change: 1 addition & 0 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ jobs:
working-directory: frontend
run: |
echo "VITE_APP_BACKEND_URL=https://api.kscale.store" >> .env.production
echo "VITE_STRIPE_PUBLISHABLE_KEY=${{ secrets.VITE_STRIPE_PUBLISHABLE_KEY }}" >> .env.production
- name: Build frontend
run: |
Expand Down
3 changes: 3 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ env:
ONSHAPE_API: ${{ secrets.ONSHAPE_API }}
ONSHAPE_ACCESS_KEY: ${{ secrets.ONSHAPE_ACCESS_KEY }}
ONSHAPE_SECRET_KEY: ${{ secrets.ONSHAPE_SECRET_KEY }}
VITE_STRIPE_PUBLISHABLE_KEY: ${{ secrets.VITE_STRIPE_PUBLISHABLE_KEY }}
STRIPE_SECRET_KEY: ${{ secrets.STRIPE_SECRET_KEY }}
STRIPE_WEBHOOK_SECRET: ${{ secrets.STRIPE_WEBHOOK_SECRET }}

jobs:
run-tests:
Expand Down
5 changes: 5 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,11 @@ export VITE_GOOGLE_CLIENT_ID=''
# For OnShape
export ONSHAPE_ACCESS_KEY=''
export ONSHAPE_SECRET_KEY=''

# For Stripe
export VITE_STRIPE_PUBLISHABLE_KEY=''
export STRIPE_SECRET_KEY=''
export STRIPE_WEBHOOK_SECRET=''
```

### Google OAuth Configuration
Expand Down
8 changes: 7 additions & 1 deletion env.sh.example
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,10 @@ export GOOGLE_CLIENT_SECRET=''

# For OnShape
export ONSHAPE_ACCESS_KEY=''
export ONSHAPE_SECRET_KEY=''
export ONSHAPE_SECRET_KEY=''

# For Stripe
# developer_mode
export VITE_STRIPE_PUBLISHABLE_KEY=''
export STRIPE_SECRET_KEY=''
export STRIPE_WEBHOOK_SECRET=''
5 changes: 2 additions & 3 deletions frontend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
"@react-oauth/google": "^0.12.1",
"@react-three/drei": "^9.109.2",
"@react-three/fiber": "^8.16.8",
"@stripe/stripe-js": "^1.54.2",
"@types/three": "^0.168.0",
"@uidotdev/usehooks": "^2.4.1",
"@uiw/react-codemirror": "^4.23.5",
Expand Down
9 changes: 8 additions & 1 deletion frontend/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ import { AuthenticationProvider } from "@/hooks/useAuth";
import GDPRBanner from "./components/gdpr/gdprbanner";
import DownloadsPage from "./components/pages/Download";
import MuJoCoTestPage from "./components/pages/MuJoCoTest";
import OrderCancel from "./components/pages/OrderCancel";
import OrderSuccess from "./components/pages/OrderSuccess";
import Orders from "./components/pages/Orders";
import PrivacyPolicy from "./components/pages/PrivacyPolicy";
import ResearchPage from "./components/pages/ResearchPage";
import TermsOfService from "./components/pages/TermsOfService";
Expand All @@ -55,7 +58,6 @@ const App = () => {
<Route path="/mujoco-test" element={<MuJoCoTestPage />} />

<Route path="/about" element={<About />} />
<Route path="/buy" element={<BuyPage />} />
<Route path="/downloads" element={<DownloadsPage />} />
<Route path="/research" element={<ResearchPage />} />
<Route path="/k-lang" element={<KLangPage />} />
Expand All @@ -78,6 +80,11 @@ const App = () => {
<Route path="/tos" element={<TermsOfService />} />
<Route path="/privacy" element={<PrivacyPolicy />} />

<Route path="/buy" element={<BuyPage />} />
<Route path="/success" element={<OrderSuccess />} />
<Route path="/cancel" element={<OrderCancel />} />
<Route path="/orders" element={<Orders />} />

<Route path="/404" element={<NotFound />} />
<Route path="*" element={<NotFoundRedirect />} />
</Routes>
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/Container.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ const Container = (props: ContainerProps) => {
const { children } = props;

return (
<div className="mt-[68px] mb-6 mx-4 sm:mx-6 md:mx-10 xl:mx-16 max-w-full">
<div className="mt-20 mb-6 mx-4 sm:mx-6 md:mx-10 xl:mx-16 max-w-full">
{children}
</div>
);
Expand Down
94 changes: 94 additions & 0 deletions frontend/src/components/Drawer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import React from "react";
import useMeasure from "react-use-measure";

import {
motion,
useAnimate,
useDragControls,
useMotionValue,
} from "framer-motion";

export const Drawer = ({
open,
setOpen,
children,
}: {
open: boolean;
setOpen: (open: boolean) => void;
children: React.ReactNode;
}) => {
const [scope, animate] = useAnimate();
const [drawerRef, { height }] = useMeasure();

const y = useMotionValue(0);
const controls = useDragControls();

const handleClose = async () => {
animate(scope.current, {
opacity: [1, 0],
});

const yStart = typeof y.get() === "number" ? y.get() : 0;

await animate("#drawer", {
y: [yStart, height],
});

setOpen(false);
};

return (
<>
{open && (
<motion.div
ref={scope}
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
onClick={handleClose}
className="fixed inset-0 z-50 bg-neutral-950/70"
>
<motion.div
id="drawer"
ref={drawerRef}
onClick={(e) => e.stopPropagation()}
initial={{ y: "100%" }}
animate={{ y: "0%" }}
transition={{
ease: "easeInOut",
}}
className="absolute bottom-0 h-[75vh] w-full overflow-hidden rounded-t-3xl bg-neutral-900"
style={{ y }}
drag="y"
dragControls={controls}
onDragEnd={() => {
if (y.get() >= 100) {
handleClose();
}
}}
dragListener={false}
dragConstraints={{
top: 0,
bottom: 0,
}}
dragElastic={{
top: 0,
bottom: 0.5,
}}
>
<div className="absolute left-0 right-0 top-0 z-10 flex justify-center bg-neutral-900 p-4">
<button
onPointerDown={(e) => {
controls.start(e);
}}
className="h-2 w-14 cursor-grab touch-none rounded-full bg-neutral-700 active:cursor-grabbing"
></button>
</div>
<div className="relative z-0 h-full overflow-y-scroll p-4 pt-12">
{children}
</div>
</motion.div>
</motion.div>
)}
</>
);
};
16 changes: 11 additions & 5 deletions frontend/src/components/home/BuySection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -75,26 +75,32 @@ export default function BuySection() {
<ul className="grid gap-6 text-gray-1">
<li>
<div className="grid gap-1">
<h3 className="text-xl font-bold">Advanced AI</h3>
<h3 className="text-xl font-bold">
Program Your Robot to Do Anything
</h3>
<p className="text-gray-8">
Powered by the latest artificial intelligence algorithms.
Powered by K-Lang, our neural network integrated programming
language. You can tell your robot to do anything and it will
learn and improve over time based on positive and negative
reinforcement feedback loops.
</p>
</div>
</li>
<li>
<div className="grid gap-1">
<h3 className="text-xl font-bold">Build Quality</h3>
<p className="text-gray-8">
Built with a high-quality aluminum frame, and the best
Built with an aircraft grade aluminum frame, and the best
motors, actuators, and sensors available.
</p>
</div>
</li>
<li>
<div className="grid gap-1">
<h3 className="text-xl font-bold">24/7 Operation</h3>
<h3 className="text-xl font-bold">Swappable Batteries</h3>
<p className="text-gray-8">
Designed for continuous operation without downtime.
Stompy Pro comes with a removable battery pack that can be
swapped out for a charged one when needed.
</p>
</div>
</li>
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/nav/Navbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ const Navbar = () => {
return (
<>
<nav className="fixed w-full z-30 top-0 start-0 bg-gray-1/30 backdrop-blur-lg">
<div className="flex items-center justify-between py-2 mx-4 sm:mx-6 md:mx-10 xl:mx-16 font-medium">
<div className="flex items-center justify-between py-3 mx-4 sm:mx-6 md:mx-10 xl:mx-16 font-medium">
<Link
to="/"
className="flex items-center space-x-2 bg-gray-12 p-3 rounded-lg hover:bg-primary-9 transition-all duration-300"
Expand Down
Loading

0 comments on commit ad10447

Please sign in to comment.