diff --git a/apps/platform/public/svg/shared/Error.svg b/apps/platform/public/svg/shared/Error.svg
new file mode 100644
index 00000000..6b5ae5ea
--- /dev/null
+++ b/apps/platform/public/svg/shared/Error.svg
@@ -0,0 +1,3 @@
+
diff --git a/apps/platform/public/svg/shared/Vector.svg b/apps/platform/public/svg/shared/Vector.svg
new file mode 100644
index 00000000..c7aad118
--- /dev/null
+++ b/apps/platform/public/svg/shared/Vector.svg
@@ -0,0 +1,3 @@
+
diff --git a/apps/platform/public/svg/shared/index.ts b/apps/platform/public/svg/shared/index.ts
index 07133a8c..0d09dde2 100644
--- a/apps/platform/public/svg/shared/index.ts
+++ b/apps/platform/public/svg/shared/index.ts
@@ -7,6 +7,9 @@ import SettingsSVG from './settings.svg'
import ThreeDotOptionSVG from './3dotOption.svg'
import AddSVG from './add.svg'
import LoadingSVG from './loading.svg'
+import MessageSVG from './message.svg'
+import VectorSVG from './vector.svg'
+import ErrorSVG from './Error.svg'
export {
DropdownSVG,
@@ -17,5 +20,8 @@ export {
SettingsSVG,
ThreeDotOptionSVG,
AddSVG,
- LoadingSVG
+ LoadingSVG,
+ MessageSVG,
+ VectorSVG,
+ ErrorSVG
}
diff --git a/apps/platform/public/svg/shared/message.svg b/apps/platform/public/svg/shared/message.svg
new file mode 100644
index 00000000..f7757498
--- /dev/null
+++ b/apps/platform/public/svg/shared/message.svg
@@ -0,0 +1,3 @@
+
diff --git a/apps/platform/src/app/(main)/project/[project]/@variable/page.tsx b/apps/platform/src/app/(main)/project/[project]/@variable/page.tsx
index a4362de4..4557192f 100644
--- a/apps/platform/src/app/(main)/project/[project]/@variable/page.tsx
+++ b/apps/platform/src/app/(main)/project/[project]/@variable/page.tsx
@@ -1,7 +1,174 @@
-import React from 'react'
+'use client'
-function VariablePage(): React.JSX.Element {
- return
VariablePage
+import { useEffect, useState } from 'react'
+import { Button } from '@/components/ui/button'
+import { VariableController } from '@keyshade/api-client'
+import {
+ ClientResponse,
+ GetAllVariablesOfProjectResponse,
+ Project,
+} from '@keyshade/schema'
+import { FolderSVG } from '@public/svg/dashboard'
+import { MessageSVG } from '@public/svg/shared'
+import { ChevronDown, ChevronUp, MessageSquare } from 'lucide-react'
+import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar'
+import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "@/components/ui/collapsible"
+import {
+ Table,
+ TableBody,
+ TableCell,
+ TableHead,
+ TableHeader,
+ TableRow
+} from '@/components/ui/table'
+
+interface VariablePageProps {
+ currentProject: Project | undefined
+ // availableEnvironments: Environment[]
+}
+
+
+function VariablePage({
+ currentProject
+ // availableEnvironments
+}: VariablePageProps): React.JSX.Element {
+
+ const [allVariables, setAllVariables] = useState([])
+ // Holds the currently open section ID
+ const [openSections, setOpenSections] = useState>(new Set())
+
+ const toggleSection = (id: string) => {
+ setOpenSections((prev) => {
+ const newSet = new Set(prev)
+ if (newSet.has(id)) {
+ newSet.delete(id)
+ } else {
+ newSet.add(id)
+ }
+ return newSet
+ })
+ }
+
+ useEffect(() => {
+ const variableController = new VariableController(
+ process.env.NEXT_PUBLIC_BACKEND_URL
+ )
+
+ const getVariables = async () => {
+ const {
+ success,
+ error,
+ data
+ }: ClientResponse =
+ await variableController.getAllVariablesOfProject(
+ { projectSlug: currentProject?.slug },
+ {}
+ )
+
+ if (success && data) {
+ setAllVariables(data.items)
+ } else {
+ // eslint-disable-next-line no-console -- we need to log the error
+ console.error(error)
+ }
+ }
+
+ getVariables()
+ }, [currentProject])
+
+ return (
+
+ {/* Showing this when there are no variables present */}
+ {allVariables.length === 0 ? (
+
+
+
+
+
+ Declare your first variable
+
+
+ Declare and store a variable against different environments
+
+
+
+
+
+ ) : (
+
+ {allVariables.map((variable) => (
+
toggleSection(variable.variable.id)}
+ className="w-full"
+ >
+
+
+
+ {variable.variable.name}
+
+
+
+
+
+
+ {(() => {
+ const days = Math.ceil(Math.abs(new Date().getTime() - new Date(variable.variable.createdAt).getTime()) / (1000 * 60 * 60 * 24));
+ return `${days} ${days === 1 ? 'day' : 'days'} ago by`;
+ })()}
+
+
+
+ {variable.variable.lastUpdatedBy.name.split(' ')[0]}
+
+
+
+
+ {variable.variable.lastUpdatedBy.name.charAt(0).toUpperCase() + variable.variable.lastUpdatedBy.name.slice(1, 2).toLowerCase()}
+
+
+
+
+
+
+
+
+ {variable.values ? (
+
+
+
+ Environment
+ Value
+
+
+
+ {variable.values.map((env) => (
+
+
+ {env.environment.name}
+
+
+ {env.value}
+
+
+ ))}
+
+
+ ) : (
+
+ No content available for this section.
+
+ )}
+
+
+ ))}
+
+ )}
+
+ )
}
export default VariablePage
diff --git a/apps/platform/src/app/(main)/project/[project]/layout.tsx b/apps/platform/src/app/(main)/project/[project]/layout.tsx
index 8a747ac4..23f5b560 100644
--- a/apps/platform/src/app/(main)/project/[project]/layout.tsx
+++ b/apps/platform/src/app/(main)/project/[project]/layout.tsx
@@ -1,7 +1,8 @@
'use client'
+
import { useEffect, useState } from 'react'
import { useSearchParams } from 'next/navigation'
-import { AddSVG } from '@public/svg/shared'
+import { AddSVG, ErrorSVG, VectorSVG } from '@public/svg/shared'
import { Button } from '@/components/ui/button'
import {
Dialog,
@@ -11,10 +12,30 @@ import {
DialogTitle,
DialogTrigger
} from '@/components/ui/dialog'
+import {
+ Select,
+ SelectContent,
+ SelectItem,
+ SelectTrigger,
+ SelectValue
+} from '@/components/ui/select'
import { Input } from '@/components/ui/input'
import { Label } from '@/components/ui/label'
-import type { Project } from '@/types'
-import { Projects } from '@/lib/api-functions/projects'
+import {
+ ProjectController,
+ EnvironmentController,
+ VariableController
+} from '@keyshade/api-client'
+import {
+ ClientResponse,
+ CreateVariableRequest,
+ Environment,
+ GetAllEnvironmentsOfProjectResponse,
+ Project
+} from '@keyshade/schema'
+import VariablePage from './@variable/page'
+import { toast } from "sonner"
+import { Toaster } from '@/components/ui/sonner'
interface DetailedProjectPageProps {
params: { project: string }
@@ -31,84 +52,339 @@ function DetailedProjectPage({
const [key, setKey] = useState('')
// eslint-disable-next-line @typescript-eslint/no-unused-vars -- will be used later
const [value, setValue] = useState('')
-
const [currentProject, setCurrentProject] = useState()
const searchParams = useSearchParams()
const tab = searchParams.get('tab') ?? 'rollup-details'
useEffect(() => {
- Projects.getProjectbyID(params.project)
- .then((project) => {
- setCurrentProject(project)
- })
- .catch((error) => {
+ const getCurrentProject = async () => {
+ const projectController = new ProjectController(
+ process.env.NEXT_PUBLIC_BACKEND_URL
+ )
+
+ const { success, error, data } = await projectController.getProject(
+ { projectSlug: params.project },
+ {}
+ )
+
+ if (success && data) {
+ setCurrentProject(data as Project)
+ } else {
// eslint-disable-next-line no-console -- we need to log the error
console.error(error)
- })
+ }
+ }
+
+ getCurrentProject()
}, [params.project])
+
+ //VARIABLES PART
+ const [isOpen, setIsOpen] = useState(false)
+ const [newVariableData, setNewVariableData] = useState({
+ variableName: '',
+ note: '',
+ environmentName: '',
+ environmentValue: ''
+ })
+ const [availableEnvironments, setAvailableEnvironments] = useState<
+ Environment[]
+ >([])
+
+
+ const addVariable = async (e: any) => {
+
+ e.preventDefault()
+
+ const variableController = new VariableController(
+ process.env.NEXT_PUBLIC_BACKEND_URL
+ )
+
+ const request: CreateVariableRequest = {
+ name: newVariableData.variableName,
+ projectSlug: currentProject?.slug as string,
+ entries: newVariableData.environmentValue
+ ? [
+ {
+ value: newVariableData.environmentValue,
+ environmentSlug: newVariableData.environmentName
+ }
+ ]
+ : undefined,
+ note: newVariableData.note
+ }
+
+ const { success, error, data } = await variableController.createVariable(
+ request,
+ {}
+ )
+
+ if( success ){
+ toast(
+
+
+
+
+
Variable created successfully
+
You created new variable
+
+
+
, {
+ style: { height: '4.5rem', width: '23.438rem', borderRadius: '0.375rem', backgroundColor: '#022C22', color: '#6EE7B7', overflow: 'hidden' }
+ })
+ }
+ if( error ){
+ toast(
+
+
+
+
+
Variable name already exists
+
Variable name is already there, kindly use different one
+
+
+
, {
+ style: { height: '4.5rem', width: '23.438rem', borderRadius: '0.375rem', backgroundColor: '#450A0A', color: '#E92D1F', overflow: 'hidden' }
+ })
+ }
+
+ setNewVariableData({
+ variableName: '',
+ note: '',
+ environmentName: '',
+ environmentValue: ''
+ })
+
+ setIsOpen(false)
+ }
+
+ useEffect(() => {
+ const getAllEnvironments = async () => {
+ const environmentController = new EnvironmentController(
+ process.env.NEXT_PUBLIC_BACKEND_URL
+ )
+
+ const {
+ success,
+ error,
+ data
+ }: ClientResponse =
+ await environmentController.getAllEnvironmentsOfProject(
+ { projectSlug: currentProject!.slug },
+ {}
+ )
+
+ if (success && data) {
+ setAvailableEnvironments(data.items)
+ } else {
+ // eslint-disable-next-line no-console -- we need to log the error
+ console.error(error)
+ }
+ }
+
+ getAllEnvironments()
+ }, [currentProject])
+
+ useEffect(() => {
+ console.log('Value inside the env state: ', availableEnvironments)
+ }, [availableEnvironments])
+
return (
-
+
{currentProject?.name}
-