Skip to content

Commit 71a47a1

Browse files
author
Gerome El-assaad
committed
refactor: Update UI components and page layouts
1 parent 3715e94 commit 71a47a1

6 files changed

Lines changed: 217 additions & 72 deletions

File tree

app/layout.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,12 @@ import { GeistMono } from 'geist/font/mono'
77
import { Analytics } from "@vercel/analytics/next"
88
import { SpeedInsights } from "@vercel/speed-insights/next"
99
import Script from 'next/script'
10-
import r from 'react-syntax-highlighter/dist/esm/languages/hljs/r'
10+
import { validateEnvironmentOnStartup } from '@/lib/env-validation'
11+
12+
// Validate environment variables on startup
13+
if (typeof window === 'undefined') {
14+
validateEnvironmentOnStartup()
15+
}
1116

1217
export const metadata: Metadata = {
1318
metadataBase: new URL('https://codingit.vercel.app'),

app/page.tsx

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import { usePostHog } from 'posthog-js/react'
2525
import { SetStateAction, useCallback, useEffect, useState } from 'react'
2626
import { useLocalStorage } from 'usehooks-ts'
2727
import { useEnhancedChat } from '@/hooks/use-enhanced-chat'
28+
import { useUserTeam } from '@/lib/user-team-provider'
2829
import { HeroPillSecond } from '@/components/announcement'
2930
import { useAnalytics } from '@/lib/analytics-service'
3031

@@ -69,7 +70,8 @@ export default function Home() {
6970
const [currentProject, setCurrentProject] = useState<Project | null>(null)
7071
const [isLoadingProject, setIsLoadingProject] = useState(false)
7172

72-
const { session, userTeam } = useAuth(setAuthDialogCallback, setAuthViewCallback)
73+
const { session } = useAuth(setAuthDialogCallback, setAuthViewCallback)
74+
const { userTeam } = useUserTeam()
7375

7476

7577
const { executeCode: enhancedExecuteCode } = useEnhancedChat({
@@ -310,11 +312,16 @@ export default function Home() {
310312
const updatedMessages = [...messages, newMessage]
311313
setMessages(updatedMessages)
312314

315+
const templateToSend =
316+
selectedTemplate === 'auto'
317+
? templates
318+
: { [selectedTemplate]: templates[selectedTemplate] }
319+
313320
submit({
314321
userID: session?.user?.id,
315322
teamID: userTeam?.id,
316323
messages: toAISDKMessages(updatedMessages),
317-
template: templates,
324+
template: templateToSend,
318325
model: currentModel,
319326
config: languageModel,
320327
})

app/settings/privacy/page.tsx

Lines changed: 147 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/com
55
import { Switch } from '@/components/ui/switch'
66
import { Separator } from '@/components/ui/separator'
77
import { useToast } from '@/components/ui/use-toast'
8+
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip'
89
import {
910
Shield,
1011
Download,
@@ -18,6 +19,7 @@ import {
1819
} from 'lucide-react'
1920
import { useState, useEffect } from 'react'
2021
import { useAuth } from '@/lib/auth'
22+
import { useUserTeam } from '@/lib/user-team-provider'
2123
import {
2224
getUserPreferences,
2325
updateUserPreferences,
@@ -35,8 +37,11 @@ interface PrivacySettings {
3537

3638
export default function PrivacySettings() {
3739
const { session } = useAuth(() => {}, () => {})
40+
const { userTeam } = useUserTeam()
3841
const { toast } = useToast()
3942

43+
const isFreeUser = userTeam?.tier === 'free'
44+
4045
const [privacySettings, setPrivacySettings] = useState<PrivacySettings>({
4146
analytics_enabled: true,
4247
marketing_emails: false,
@@ -291,11 +296,22 @@ export default function PrivacySettings() {
291296
Help us improve the platform by sharing anonymous usage data
292297
</p>
293298
</div>
294-
<Switch
295-
checked={privacySettings.analytics_enabled}
296-
onCheckedChange={(checked: boolean) => handleUpdateSetting('analytics_enabled', checked)}
297-
disabled={isUpdating}
298-
/>
299+
<TooltipProvider>
300+
<Tooltip>
301+
<TooltipTrigger asChild>
302+
<Switch
303+
checked={privacySettings.analytics_enabled}
304+
onCheckedChange={(checked: boolean) => handleUpdateSetting('analytics_enabled', checked)}
305+
disabled={isUpdating || isFreeUser}
306+
/>
307+
</TooltipTrigger>
308+
{isFreeUser && (
309+
<TooltipContent>
310+
<p>Upgrade to a paid plan to change this setting.</p>
311+
</TooltipContent>
312+
)}
313+
</Tooltip>
314+
</TooltipProvider>
299315
</div>
300316

301317
<div className="flex items-center justify-between">
@@ -308,11 +324,22 @@ export default function PrivacySettings() {
308324
Receive updates about new features, tips, and special offers
309325
</p>
310326
</div>
311-
<Switch
312-
checked={privacySettings.marketing_emails}
313-
onCheckedChange={(checked: boolean) => handleUpdateSetting('marketing_emails', checked)}
314-
disabled={isUpdating}
315-
/>
327+
<TooltipProvider>
328+
<Tooltip>
329+
<TooltipTrigger asChild>
330+
<Switch
331+
checked={privacySettings.marketing_emails}
332+
onCheckedChange={(checked: boolean) => handleUpdateSetting('marketing_emails', checked)}
333+
disabled={isUpdating || isFreeUser}
334+
/>
335+
</TooltipTrigger>
336+
{isFreeUser && (
337+
<TooltipContent>
338+
<p>Upgrade to a paid plan to change this setting.</p>
339+
</TooltipContent>
340+
)}
341+
</Tooltip>
342+
</TooltipProvider>
316343
</div>
317344

318345
<div className="flex items-center justify-between">
@@ -325,11 +352,22 @@ export default function PrivacySettings() {
325352
Share aggregated, anonymous data with research partners
326353
</p>
327354
</div>
328-
<Switch
329-
checked={privacySettings.data_sharing}
330-
onCheckedChange={(checked: boolean) => handleUpdateSetting('data_sharing', checked)}
331-
disabled={isUpdating}
332-
/>
355+
<TooltipProvider>
356+
<Tooltip>
357+
<TooltipTrigger asChild>
358+
<Switch
359+
checked={privacySettings.data_sharing}
360+
onCheckedChange={(checked: boolean) => handleUpdateSetting('data_sharing', checked)}
361+
disabled={isUpdating || isFreeUser}
362+
/>
363+
</TooltipTrigger>
364+
{isFreeUser && (
365+
<TooltipContent>
366+
<p>Upgrade to a paid plan to change this setting.</p>
367+
</TooltipContent>
368+
)}
369+
</Tooltip>
370+
</TooltipProvider>
333371
</div>
334372

335373
<div className="flex items-center justify-between">
@@ -342,11 +380,22 @@ export default function PrivacySettings() {
342380
Track your activity to provide personalized recommendations
343381
</p>
344382
</div>
345-
<Switch
346-
checked={privacySettings.activity_tracking}
347-
onCheckedChange={(checked: boolean) => handleUpdateSetting('activity_tracking', checked)}
348-
disabled={isUpdating}
349-
/>
383+
<TooltipProvider>
384+
<Tooltip>
385+
<TooltipTrigger asChild>
386+
<Switch
387+
checked={privacySettings.activity_tracking}
388+
onCheckedChange={(checked: boolean) => handleUpdateSetting('activity_tracking', checked)}
389+
disabled={isUpdating || isFreeUser}
390+
/>
391+
</TooltipTrigger>
392+
{isFreeUser && (
393+
<TooltipContent>
394+
<p>Upgrade to a paid plan to change this setting.</p>
395+
</TooltipContent>
396+
)}
397+
</Tooltip>
398+
</TooltipProvider>
350399
</div>
351400

352401
<div className="flex items-center justify-between">
@@ -359,11 +408,22 @@ export default function PrivacySettings() {
359408
Customize the interface and content based on your preferences
360409
</p>
361410
</div>
362-
<Switch
363-
checked={privacySettings.personalization}
364-
onCheckedChange={(checked: boolean) => handleUpdateSetting('personalization', checked)}
365-
disabled={isUpdating}
366-
/>
411+
<TooltipProvider>
412+
<Tooltip>
413+
<TooltipTrigger asChild>
414+
<Switch
415+
checked={privacySettings.personalization}
416+
onCheckedChange={(checked: boolean) => handleUpdateSetting('personalization', checked)}
417+
disabled={isUpdating || isFreeUser}
418+
/>
419+
</TooltipTrigger>
420+
{isFreeUser && (
421+
<TooltipContent>
422+
<p>Upgrade to a paid plan to change this setting.</p>
423+
</TooltipContent>
424+
)}
425+
</Tooltip>
426+
</TooltipProvider>
367427
</div>
368428

369429
<div className="flex items-center justify-between">
@@ -376,11 +436,22 @@ export default function PrivacySettings() {
376436
Help us improve our products and services by sharing anonymous usage data. This data may be sold to third parties.
377437
</p>
378438
</div>
379-
<Switch
380-
checked={privacySettings.telemetry_enabled}
381-
onCheckedChange={(checked: boolean) => handleUpdateSetting('telemetry_enabled', checked)}
382-
disabled={isUpdating}
383-
/>
439+
<TooltipProvider>
440+
<Tooltip>
441+
<TooltipTrigger asChild>
442+
<Switch
443+
checked={privacySettings.telemetry_enabled}
444+
onCheckedChange={(checked: boolean) => handleUpdateSetting('telemetry_enabled', checked)}
445+
disabled={isUpdating || isFreeUser}
446+
/>
447+
</TooltipTrigger>
448+
{isFreeUser && (
449+
<TooltipContent>
450+
<p>Upgrade to a paid plan to change this setting.</p>
451+
</TooltipContent>
452+
)}
453+
</Tooltip>
454+
</TooltipProvider>
384455
</div>
385456
</CardContent>
386457
</Card>
@@ -401,18 +472,29 @@ export default function PrivacySettings() {
401472
Download a copy of all your personal data including projects, preferences, and usage history
402473
</p>
403474
</div>
404-
<Button
405-
variant="outline"
406-
onClick={handleExportData}
407-
disabled={isExporting}
408-
>
409-
{isExporting ? (
410-
<Loader2 className="h-4 w-4 mr-2 animate-spin" />
411-
) : (
412-
<Download className="h-4 w-4 mr-2" />
413-
)}
414-
{isExporting ? 'Exporting...' : 'Export Data'}
415-
</Button>
475+
<TooltipProvider>
476+
<Tooltip>
477+
<TooltipTrigger asChild>
478+
<Button
479+
variant="outline"
480+
onClick={handleExportData}
481+
disabled={isExporting || isFreeUser}
482+
>
483+
{isExporting ? (
484+
<Loader2 className="h-4 w-4 mr-2 animate-spin" />
485+
) : (
486+
<Download className="h-4 w-4 mr-2" />
487+
)}
488+
{isExporting ? 'Exporting...' : 'Export Data'}
489+
</Button>
490+
</TooltipTrigger>
491+
{isFreeUser && (
492+
<TooltipContent>
493+
<p>Upgrade to a paid plan to use this feature.</p>
494+
</TooltipContent>
495+
)}
496+
</Tooltip>
497+
</TooltipProvider>
416498
</div>
417499

418500
<Separator />
@@ -427,18 +509,29 @@ export default function PrivacySettings() {
427509
Permanently delete your account and all associated data. This action cannot be undone.
428510
</p>
429511
</div>
430-
<Button
431-
variant="destructive"
432-
onClick={handleDeleteAccount}
433-
disabled={isDeletingAccount}
434-
>
435-
{isDeletingAccount ? (
436-
<Loader2 className="h-4 w-4 mr-2 animate-spin" />
437-
) : (
438-
<Trash2 className="h-4 w-4 mr-2" />
439-
)}
440-
{isDeletingAccount ? 'Deleting...' : 'Delete Account'}
441-
</Button>
512+
<TooltipProvider>
513+
<Tooltip>
514+
<TooltipTrigger asChild>
515+
<Button
516+
variant="destructive"
517+
onClick={handleDeleteAccount}
518+
disabled={isDeletingAccount || isFreeUser}
519+
>
520+
{isDeletingAccount ? (
521+
<Loader2 className="h-4 w-4 mr-2 animate-spin" />
522+
) : (
523+
<Trash2 className="h-4 w-4 mr-2" />
524+
)}
525+
{isDeletingAccount ? 'Deleting...' : 'Delete Account'}
526+
</Button>
527+
</TooltipTrigger>
528+
{isFreeUser && (
529+
<TooltipContent>
530+
<p>Upgrade to a paid plan to use this feature.</p>
531+
</TooltipContent>
532+
)}
533+
</Tooltip>
534+
</TooltipProvider>
442535
</div>
443536
</CardContent>
444537
</Card>

components/code-view.tsx

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,50 @@
1-
// import "prismjs/plugins/line-numbers/prism-line-numbers.js";
2-
// import "prismjs/plugins/line-numbers/prism-line-numbers.css";
1+
import { useEffect, useRef } from 'react'
2+
import 'prismjs'
3+
import { readonlyEditor } from 'prism-code-editor/setups'
4+
import 'prism-code-editor/themes/prism-tomorrow.css'
5+
import 'prism-code-editor/layout.css'
6+
import 'prism-code-editor/scrollbar.css'
37
import './code-theme.css'
4-
import Prism from 'prismjs'
58
import 'prismjs/components/prism-javascript'
69
import 'prismjs/components/prism-jsx'
710
import 'prismjs/components/prism-python'
811
import 'prismjs/components/prism-tsx'
912
import 'prismjs/components/prism-typescript'
10-
import { useEffect } from 'react'
1113

1214
export function CodeView({ code, lang }: { code: string; lang: string }) {
15+
const editorRef = useRef<HTMLDivElement>(null)
16+
const editor = useRef<any>(null)
17+
18+
useEffect(() => {
19+
if (typeof window !== 'undefined') {
20+
if (editorRef.current && !editor.current) {
21+
editor.current = readonlyEditor(editorRef.current, {
22+
language: lang,
23+
value: code,
24+
wordWrap: true,
25+
theme: 'prism-tomorrow',
26+
})
27+
}
28+
}
29+
}, [lang, code])
30+
1331
useEffect(() => {
14-
Prism.highlightAll()
32+
if (editor.current) {
33+
editor.current.setOptions({ value: code })
34+
}
1535
}, [code])
1636

1737
return (
18-
<pre
38+
<div
39+
ref={editorRef}
1940
className="p-4 pt-2"
2041
style={{
2142
fontSize: 12,
2243
backgroundColor: 'transparent',
2344
borderRadius: 0,
2445
margin: 0,
46+
height: '100%',
2547
}}
26-
>
27-
<code className={`language-${lang}`}>{code}</code>
28-
</pre>
48+
/>
2949
)
30-
}
50+
}

0 commit comments

Comments
 (0)