Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 4 additions & 64 deletions apps/web/app/dashboard/page.tsx
Original file line number Diff line number Diff line change
@@ -1,78 +1,18 @@
import { GenerateImage } from "@/components/GenerateImage";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { Train } from "@/components/Train";
import { Packs } from "@/components/Packs";
import { Camera } from "@/components/Camera";
import { redirect } from "next/navigation";
import { auth } from "@clerk/nextjs/server";
import { DashboardClient } from "@/components/DashboardClient";
import { getPacks } from '../../components/Packs';
export const dynamic = "force-dynamic";

export default async function DashboardPage() {
const { userId } = await auth();
const packs = await getPacks();

if (!userId) {
redirect("/");
}

return (
<div className="max-w-6xl mx-auto px-4 py-24 min-h-screen">
<div className="space-y-8">
<Tabs defaultValue="camera">
<TabsList className="inline-flex h-10 items-center justify-start rounded-lg p-1 dark:bg-muted/50 bg-pink-50">
<TabsTrigger
value="camera"
className="data-[state=active]:bg-pink-500/70 backdrop-blur-sm data-[state=active]:text-pink-50 cursor-pointer px-3 py-1.5"
>
Camera
</TabsTrigger>
<TabsTrigger
value="generate"
className="data-[state=active]:bg-pink-500/70 backdrop-blur-sm data-[state=active]:text-pink-50 cursor-pointer px-3 py-1.5"
>
Generate<span className="md:block hidden pl-1">Images</span>
</TabsTrigger>
<TabsTrigger
value="packs"
className="data-[state=active]:bg-pink-500/70 backdrop-blur-sm data-[state=active]:text-pink-50 cursor-pointer px-3 py-1.5"
>
Packs
</TabsTrigger>
<TabsTrigger
value="train"
className="data-[state=active]:bg-pink-500/70 backdrop-blur-sm data-[state=active]:text-pink-50 cursor-pointer px-3 py-1.5"
>
Train<span className="md:block hidden pl-1">Model</span>
</TabsTrigger>
</TabsList>

<div className="mt-8 bg-card rounded-lg">
<TabsContent
value="camera"
className="mt-0 focus-visible:outline-none"
>
<Camera />
</TabsContent>
<TabsContent
value="generate"
className="mt-0 focus-visible:outline-none"
>
<GenerateImage />
</TabsContent>
<TabsContent
value="packs"
className="mt-0 focus-visible:outline-none"
>
<Packs />
</TabsContent>
<TabsContent
value="train"
className="mt-0 focus-visible:outline-none"
>
<Train />
</TabsContent>
</div>
</Tabs>
</div>
</div>
<DashboardClient packs={packs}/>
);
}
79 changes: 79 additions & 0 deletions apps/web/components/DashboardClient.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
"use client"
import { GenerateImage } from "@/components/GenerateImage";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { Train } from "@/components/Train";
import { PacksClient } from "./PacksClient";
import { Camera } from "@/components/Camera";
import { Provider } from "react-redux";
import store from "../store/store";
import { TPack } from './PackCard';

export function DashboardClient({ packs }: { packs: TPack[]}){
return(
<Provider store={store}>
<div className="max-w-6xl mx-auto px-4 py-24 min-h-screen">
<div className="space-y-8">
<Tabs defaultValue="camera">
<TabsList className="inline-flex h-10 items-center justify-start rounded-lg p-1 dark:bg-muted/50 bg-pink-50">
<TabsTrigger
value="camera"
className="data-[state=active]:bg-pink-500/70 backdrop-blur-sm data-[state=active]:text-pink-50 cursor-pointer px-3 py-1.5"
>
Camera
</TabsTrigger>
<TabsTrigger
value="generate"
className="data-[state=active]:bg-pink-500/70 backdrop-blur-sm data-[state=active]:text-pink-50 cursor-pointer px-3 py-1.5"
>
Generate<span className="md:block hidden pl-1">Images</span>
</TabsTrigger>
<TabsTrigger
value="packs"
className="data-[state=active]:bg-pink-500/70 backdrop-blur-sm data-[state=active]:text-pink-50 cursor-pointer px-3 py-1.5"
>
Packs
</TabsTrigger>
<TabsTrigger
value="train"
className="data-[state=active]:bg-pink-500/70 backdrop-blur-sm data-[state=active]:text-pink-50 cursor-pointer px-3 py-1.5"
>
Train<span className="md:block hidden pl-1">Model</span>
</TabsTrigger>
</TabsList>

<div className="mt-8 bg-card rounded-lg">
<TabsContent
value="camera"
className="mt-0 focus-visible:outline-none"
>
<Camera />
</TabsContent>
<TabsContent
value="generate"
className="mt-0 focus-visible:outline-none"
>
<GenerateImage />
</TabsContent>
<TabsContent
value="packs"
className="mt-0 focus-visible:outline-none"
>
<PacksClient packs={packs} />
</TabsContent>
<TabsContent
value="train"
className="mt-0 focus-visible:outline-none"
>
<Train />
</TabsContent>
</div>
</Tabs>
</div>
</div>
</Provider>
)
}




2 changes: 1 addition & 1 deletion apps/web/components/Packs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { TPack } from "./PackCard";
import axios from "axios";
import { PacksClient } from "./PacksClient";

async function getPacks(): Promise<TPack[]> {
export async function getPacks(): Promise<TPack[]> {
const res = await axios.get(`${BACKEND_URL}/pack/bulk`);
return res.data.packs ?? [];
}
Expand Down
21 changes: 21 additions & 0 deletions apps/web/components/Train.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ import {
CarouselPrevious,
} from "@/components/ui/carousel";
import JSZip from "jszip";
import { useSelector, useDispatch } from "react-redux";
import { setModelIdStore, setModelTrainingStore } from "../store/trainModelSlice";
import { RootState } from "../store/store";

interface UploadedFile {
name: string;
Expand All @@ -64,6 +67,18 @@ export function Train() {
const [uploadProgress, setUploadProgress] = useState(0);
const [modelId, setModelId] = useState<string | null>(null);
const [trainingStatus, setTrainingStatus] = useState<string | null>(null);
const modelIdStore = useSelector( (state: RootState) => state.trainModelReducer.modelIdStore );
const modelTrainingStore = useSelector( (state: RootState) => state.trainModelReducer.modelTrainingStore );
const dispatch = useDispatch();

// Check upon the component mount if any model is already training
useEffect( () => {
console.log("inside useEffect 1")
if(modelTrainingStore && modelIdStore){
setModelId(modelIdStore);
setModelTraining(modelTrainingStore);
}
}, [] )

// Check training status periodically if we have a modelId
useEffect(() => {
Expand Down Expand Up @@ -94,7 +109,9 @@ export function Train() {
toast.error("Model training failed. Please try again.");
}
setModelId(null);
dispatch(setModelIdStore(null));
setModelTraining(false);
dispatch(setModelTrainingStore(false));
}
}
} catch (error) {
Expand Down Expand Up @@ -143,19 +160,22 @@ export function Train() {
try {
const token = await getToken();
setModelTraining(true);
dispatch(setModelTrainingStore(true));

const response = await axios.post(`${BACKEND_URL}/ai/training`, input, {
headers: { Authorization: `Bearer ${token}` },
});

if (response.data.modelId) {
setModelId(response.data.modelId);
dispatch(setModelIdStore(response.data.modelId));
toast.success(
"Model training started! This will take approximately 20 minutes."
);
} else {
toast.error("Failed to start model training");
setModelTraining(false);
dispatch(setModelTrainingStore(false));
}
} catch (error) {
console.error("Training error:", error);
Expand All @@ -164,6 +184,7 @@ export function Train() {
"Failed to start model training"
);
setModelTraining(false);
dispatch(setModelTrainingStore(false));
}
}

Expand Down
2 changes: 2 additions & 0 deletions apps/web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"@radix-ui/react-tabs": "^1.1.3",
"@radix-ui/react-toast": "^1.2.6",
"@radix-ui/react-tooltip": "^1.1.8",
"@reduxjs/toolkit": "^2.8.2",
"@repo/ui": "*",
"@stripe/stripe-js": "^5.6.0",
"@tailwindcss/postcss": "^4.0.6",
Expand All @@ -43,6 +44,7 @@
"react": "^19.0.0",
"react-dom": "^19.0.0",
"react-hot-toast": "^2.5.1",
"react-redux": "^9.2.0",
"tailwind-merge": "^3.0.1",
"tailwindcss": "^4.0.6",
"tailwindcss-animate": "^1.0.7"
Expand Down
11 changes: 11 additions & 0 deletions apps/web/store/store.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { configureStore } from "@reduxjs/toolkit";
import trainModelReducer from "./trainModelSlice";

const store = configureStore({
reducer: {
trainModelReducer: trainModelReducer
}
})

export default store;
export type RootState = ReturnType<typeof store.getState>;
27 changes: 27 additions & 0 deletions apps/web/store/trainModelSlice.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { createSlice, PayloadAction } from "@reduxjs/toolkit";

type initialStateType = {
modelIdStore: null|string ,
modelTrainingStore: boolean
}

const initialState: initialStateType = {
modelIdStore: null,
modelTrainingStore: false
}

const trainModelSlice = createSlice({
name: 'trainModelSlice',
initialState: initialState,
reducers: {
setModelIdStore: ( state, action: PayloadAction<null|string> ) => {
state.modelIdStore = action.payload
},
setModelTrainingStore: (state, action: PayloadAction<boolean>) => {
state.modelTrainingStore = action.payload
}
}
})

export default trainModelSlice.reducer;
export const { setModelIdStore, setModelTrainingStore } = trainModelSlice.actions;
Binary file modified bun.lockb
Binary file not shown.