Skip to content

Commit fef9da7

Browse files
committed
code cleanup , env eg file added,
1 parent 0275a31 commit fef9da7

File tree

10 files changed

+166
-165
lines changed

10 files changed

+166
-165
lines changed

.env.example

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# Hugging Face API Key
2+
VITE_HUGGINGFACE_API_KEY=
3+
4+
# Google OAuth Credentials
5+
GOOGLE_CLIENT_ID=
6+
GOOGLE_REDIRECT_URI=
7+
GOOGLE_REFRESH_TOKEN=

README.md

+41-15
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,18 @@
22

33
A modern web application that leverages AI to generate dynamic forms instantly with google form and xml export.
44

5-
## Overview
5+
## 🌟 Overview
66

77
AI Form Builder simplifies form creation by using artificial intelligence to generate complete form structures from natural language descriptions. Perfect for developers, product managers, and anyone who needs to quickly create professional forms.
88

9-
## Key Features
9+
## Key Features
1010

1111
- **AI-Powered Generation**: Create complex forms using simple text descriptions
12-
- **Real-time Preview**: Instantly view your generated forms {TODO}
12+
- **Real-time Preview**: Instantly view your generated forms
1313
- **Theme Support**: Built-in dark/light mode
1414
- **Google Forms Export**: Export your forms directly to Google Forms
1515
- **Responsive Design**: Fully responsive across all devices
16-
- **Type Safety**: Full TypeScript support for reliable development {TODO}
16+
- **Type Safety**: Full TypeScript support for reliable development
1717

1818
## 🛠️ Technical Stack
1919

@@ -37,7 +37,7 @@ AI Form Builder simplifies form creation by using artificial intelligence to gen
3737
1. Clone the repository:
3838

3939
```bash
40-
git clone ..
40+
git clone https://github.com/yourusername/ai-form-builder.git
4141
cd ai-form-builder
4242
```
4343

@@ -59,6 +59,8 @@ bun install
5959
cp .env.example .env
6060
```
6161

62+
Fill in your `.env` file with your credentials.
63+
6264
5. Start development servers:
6365

6466
```bash
@@ -70,22 +72,22 @@ bun run dev # Frontend only
7072
bun run server # Backend only
7173
```
7274

73-
## Environment Setup
75+
## 🔑 Environment Setup
7476

75-
Create a `.env` file with the following variables:
77+
Create a `.env` file with the following variables (DO NOT COMMIT THIS FILE):
7678

7779
```env
7880
# Frontend
79-
VITE_HUGGINGFACE_API_KEY=your_huggingface_key
81+
VITE_HUGGINGFACE_API_KEY=
8082
8183
# Backend
82-
OPENAI_API_KEY=your_openai_key
83-
GOOGLE_CLIENT_ID=your_google_client_id
84-
GOOGLE_CLIENT_SECRET=your_google_client_secret
84+
OPENAI_API_KEY=
85+
GOOGLE_CLIENT_ID=
86+
GOOGLE_CLIENT_SECRET=
8587
GOOGLE_REDIRECT_URI=http://localhost:3001/oauth2callback
8688
```
8789

88-
## Available Scripts
90+
## 📝 Available Scripts
8991

9092
- `bun run dev` - Start frontend development server
9193
- `bun run server` - Start backend server
@@ -94,20 +96,44 @@ GOOGLE_REDIRECT_URI=http://localhost:3001/oauth2callback
9496
- `bun run preview` - Preview production build
9597
- `bun run token` - Generate Google OAuth refresh token
9698

97-
## Contributing
99+
## 🔒 Security Notes
100+
101+
1. Never commit `.env` files or any files containing secrets
102+
2. Use environment variables for all sensitive data
103+
3. Keep OAuth credentials secure and never expose them in client-side code
104+
4. Regularly rotate API keys and secrets
105+
5. Use `.gitignore` to prevent accidental commits of sensitive files
106+
107+
## 🤝 Contributing
98108

99109
1. Fork the repository
100110
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
101111
3. Commit your changes (`git commit -m 'Add some amazing feature'`)
102112
4. Push to the branch (`git push origin feature/amazing-feature`)
103113
5. Open a Pull Request
104114

105-
## License
115+
## 📄 License
106116

107117
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
108118

109-
## Acknowledgments
119+
## 🙏 Acknowledgments
110120

111121
- [Shadcn UI](https://ui.shadcn.com/) for the beautiful components
112122
- [OpenAI](https://openai.com/) for AI capabilities
113123
- [Google Forms API](https://developers.google.com/forms/api) for form export functionality
124+
125+
## 🔑 Getting Google Forms Refresh Token
126+
127+
To use the Google Forms export feature, you'll need to:
128+
129+
1. Set up your Google Cloud Project and enable the Google Forms API
130+
2. Create OAuth 2.0 credentials (Client ID and Secret)
131+
3. Add them to your `.env` file
132+
4. Run the token script:
133+
```bash
134+
bun run token
135+
```
136+
5. Follow the prompts to authorize the application
137+
6. Add the resulting refresh token to your `.env` file as `GOOGLE_REFRESH_TOKEN`
138+
139+
Never commit the refresh token or any other credentials to version control!

package.json

+2-12
Original file line numberDiff line numberDiff line change
@@ -9,36 +9,26 @@
99
"preview": "vite preview",
1010
"server": "bun run server/index.ts",
1111
"dev:all": "bun run dev & bun run server",
12-
"token": "bun run scripts/get-refresh-token.ts"
12+
"token": "bun scripts/get-refresh-token.ts"
1313
},
1414
"dependencies": {
1515
"@hookform/resolvers": "^3.9.1",
16-
"@radix-ui/react-alert-dialog": "^1.1.2",
1716
"@radix-ui/react-dropdown-menu": "^2.1.2",
1817
"@radix-ui/react-label": "^2.1.0",
1918
"@radix-ui/react-slot": "^1.1.0",
2019
"@radix-ui/react-switch": "^1.1.1",
2120
"@radix-ui/react-tabs": "^1.1.1",
22-
"@radix-ui/react-toast": "^1.2.2",
23-
"@types/cors": "^2.8.17",
24-
"@types/express": "^5.0.0",
2521
"class-variance-authority": "^0.7.0",
2622
"clsx": "^2.1.1",
27-
"cors": "^2.8.5",
2823
"dotenv": "^16.4.5",
29-
"express": "^4.21.1",
3024
"googleapis": "^144.0.0",
3125
"lucide-react": "^0.454.0",
32-
"next-themes": "^0.3.0",
33-
"openai": "^4.70.2",
3426
"react": "^18.3.1",
3527
"react-dom": "^18.3.1",
36-
"react-hook-form": "^7.53.2",
3728
"react-router-dom": "^6.28.0",
3829
"sonner": "^1.6.1",
3930
"tailwind-merge": "^2.5.4",
40-
"tailwindcss-animate": "^1.0.7",
41-
"zod": "^3.23.8"
31+
"tailwindcss-animate": "^1.0.7"
4232
},
4333
"devDependencies": {
4434
"@eslint/js": "^9.13.0",

scripts/get-refresh-token.ts

+80
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
import { google } from "googleapis";
2+
import dotenv from "dotenv";
3+
import path from "path";
4+
import { OAuth2Client } from "google-auth-library";
5+
6+
// Load environment variables
7+
dotenv.config({ path: path.join(__dirname, "../.env") });
8+
9+
const REQUIRED_ENV_VARS = [
10+
"GOOGLE_CLIENT_ID",
11+
"GOOGLE_CLIENT_SECRET",
12+
"GOOGLE_REDIRECT_URI",
13+
] as const;
14+
15+
// Validate required environment variables
16+
const missingVars = REQUIRED_ENV_VARS.filter((envVar) => !process.env[envVar]);
17+
if (missingVars.length > 0) {
18+
console.error(
19+
`Missing required environment variables: ${missingVars.join(", ")}`
20+
);
21+
process.exit(1);
22+
}
23+
24+
const oauth2Client = new google.auth.OAuth2(
25+
process.env.GOOGLE_CLIENT_ID,
26+
process.env.GOOGLE_CLIENT_SECRET,
27+
process.env.GOOGLE_REDIRECT_URI
28+
) as OAuth2Client;
29+
30+
// Generate auth URL with required scope
31+
const authUrl = oauth2Client.generateAuthUrl({
32+
access_type: "offline",
33+
scope: ["https://www.googleapis.com/auth/forms"],
34+
prompt: "consent", // Force consent screen to ensure refresh token
35+
});
36+
37+
console.log("\n=== Google OAuth2 Token Generator ===");
38+
console.log("\nPlease visit this URL to authorize the application:");
39+
console.log(authUrl);
40+
41+
async function handleAuthCode(code: string): Promise<void> {
42+
try {
43+
const { tokens } = await oauth2Client.getToken(code);
44+
45+
if (!tokens.refresh_token) {
46+
throw new Error(
47+
"No refresh token received. Please ensure you've revoked previous access and try again."
48+
);
49+
}
50+
51+
console.log("\nSuccess! Your refresh token:", tokens.refresh_token);
52+
console.log("\nAdd this to your .env file as:");
53+
console.log("GOOGLE_REFRESH_TOKEN=", tokens.refresh_token);
54+
process.exit(0);
55+
} catch (error) {
56+
console.error(
57+
"\nError getting tokens:",
58+
error instanceof Error ? error.message : "Unknown error"
59+
);
60+
process.exit(1);
61+
}
62+
}
63+
64+
// Handle user input
65+
process.stdin.resume();
66+
console.log("\nEnter the code from the redirect URL: ");
67+
process.stdin.on("data", (data) => {
68+
const code = data.toString().trim();
69+
if (!code) {
70+
console.error("Please provide a valid authorization code");
71+
return;
72+
}
73+
handleAuthCode(code);
74+
});
75+
76+
// Handle process termination
77+
process.on("SIGINT", () => {
78+
console.log("\nProcess terminated by user");
79+
process.exit(0);
80+
});

src/App.css

-42
This file was deleted.

src/app/layout.tsx

-16
This file was deleted.

src/components/form-builder/AIFormBuilder.tsx

+8-51
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,15 @@
1-
import { useState, useCallback } from "react";
1+
import { useFormBuilder } from "@/hooks/useFormBuilder";
22
import { Tabs, TabsList, TabsTrigger, TabsContent } from "../ui/tabs";
33
import { BuildTab } from "./BuildTab";
44
import { SettingsTab } from "./SettingsTab";
5-
import { FormConfig } from "../../types/form";
6-
import { toast } from "sonner";
75
import { Card } from "../ui/card";
8-
import { generateFormStructure } from "../../lib/ai";
96
import { Navbar } from "../navigation/Navbar";
107
import { Sparkles } from "lucide-react";
11-
12-
// Initial form configuration
13-
const initialConfig: FormConfig = {
14-
title: "",
15-
description: "",
16-
fields: [],
17-
validation: true,
18-
helpText: true,
19-
placeholders: true,
20-
};
8+
import { initialFormConfig } from "@/constants/form";
219

2210
export function AIFormBuilder() {
23-
const [config, setConfig] = useState<FormConfig>(initialConfig);
24-
const [isGenerating, setIsGenerating] = useState(false);
25-
26-
const handleConfigChange = useCallback((newConfig: Partial<FormConfig>) => {
27-
setConfig((prev) => ({ ...prev, ...newConfig }));
28-
}, []);
29-
30-
const handleGenerate = useCallback(
31-
async (prompt: string) => {
32-
setIsGenerating(true);
33-
try {
34-
const generatedConfig = await generateFormStructure(prompt);
35-
handleConfigChange(generatedConfig);
36-
toast.success("Form generated successfully!");
37-
} catch (error) {
38-
toast.error("Failed to generate form");
39-
console.error(error);
40-
} finally {
41-
setIsGenerating(false);
42-
}
43-
},
44-
[handleConfigChange]
45-
);
11+
const { config, isGenerating, handleConfigChange, handleAIGenerate } =
12+
useFormBuilder(initialFormConfig);
4613

4714
return (
4815
<div className="min-h-screen bg-background">
@@ -67,19 +34,9 @@ export function AIFormBuilder() {
6734
<Card className="overflow-hidden border-2">
6835
<Tabs defaultValue="build" className="space-y-6">
6936
<div className="px-6 pt-6 pb-2 border-b bg-card">
70-
<TabsList className="inline-flex items-center justify-center p-1 rounded-lg h-9 bg-muted">
71-
<TabsTrigger
72-
value="build"
73-
className="inline-flex items-center justify-center whitespace-nowrap rounded-md px-3 py-1 text-sm font-medium ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:bg-background data-[state=active]:text-foreground data-[state=active]:shadow-sm"
74-
>
75-
Build
76-
</TabsTrigger>
77-
<TabsTrigger
78-
value="settings"
79-
className="inline-flex items-center justify-center whitespace-nowrap rounded-md px-3 py-1 text-sm font-medium ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:bg-background data-[state=active]:text-foreground data-[state=active]:shadow-sm"
80-
>
81-
Settings
82-
</TabsTrigger>
37+
<TabsList>
38+
<TabsTrigger value="build">Build</TabsTrigger>
39+
<TabsTrigger value="settings">Settings</TabsTrigger>
8340
</TabsList>
8441
</div>
8542

@@ -88,7 +45,7 @@ export function AIFormBuilder() {
8845
<BuildTab
8946
config={config}
9047
isGenerating={isGenerating}
91-
onGenerate={handleGenerate}
48+
onGenerate={handleAIGenerate}
9249
/>
9350
</TabsContent>
9451

0 commit comments

Comments
 (0)