mirror of
https://github.com/freedbygrace/DynamoDNS.git
synced 2026-08-03 14:57:43 +00:00
Add organization management to the dashboard and authentication
Replit-Commit-Author: Agent Replit-Commit-Session-Id: 9111ef36-26c8-4085-84ca-a35dc1fec1b5 Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/7083d608-d6d3-4a6a-9a27-6286c5109627/e253bb9d-e465-4b95-aa04-9c7925837b19.jpg
This commit is contained in:
@@ -0,0 +1,88 @@
|
||||
import { Organization } from "@shared/schema";
|
||||
import { Card, CardContent, CardHeader, CardTitle, CardDescription } from "@/components/ui/card";
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import { Building, Users, Calendar } from "lucide-react";
|
||||
import { format } from "date-fns";
|
||||
import { useOrganization } from "@/context/organization-context";
|
||||
|
||||
interface OrganizationListCardProps {
|
||||
organizations: Organization[];
|
||||
}
|
||||
|
||||
export function OrganizationListCard({ organizations }: OrganizationListCardProps) {
|
||||
const { currentOrganization, setCurrentOrganization } = useOrganization();
|
||||
|
||||
if (!organizations || organizations.length === 0) {
|
||||
return (
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle>Organizations</CardTitle>
|
||||
<CardDescription>
|
||||
You don't have any organizations yet.
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="flex items-center justify-center h-40">
|
||||
<p className="text-muted-foreground">
|
||||
Create an organization in the settings page.
|
||||
</p>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle className="flex items-center">
|
||||
<Building className="h-5 w-5 mr-2" />
|
||||
Organizations
|
||||
</CardTitle>
|
||||
<CardDescription>
|
||||
Select an organization to manage its resources
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="space-y-3">
|
||||
{organizations.map((org) => (
|
||||
<div
|
||||
key={org.id}
|
||||
className={`p-4 rounded-lg border transition-all cursor-pointer
|
||||
hover:bg-accent/50
|
||||
${currentOrganization?.id === org.id ? 'border-primary bg-primary/5' : 'border-border'}
|
||||
`}
|
||||
onClick={() => setCurrentOrganization(org)}
|
||||
>
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex items-center">
|
||||
<div className="font-medium">{org.name}</div>
|
||||
{!org.isActive && (
|
||||
<Badge variant="outline" className="ml-2 text-muted-foreground">
|
||||
Inactive
|
||||
</Badge>
|
||||
)}
|
||||
</div>
|
||||
<div>
|
||||
{currentOrganization?.id === org.id && (
|
||||
<Badge className="bg-primary">Current</Badge>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex mt-2 text-xs text-muted-foreground">
|
||||
<div className="flex items-center mr-4">
|
||||
<Users className="h-3 w-3 mr-1" />
|
||||
<span>3 Members</span>
|
||||
</div>
|
||||
<div className="flex items-center">
|
||||
<Calendar className="h-3 w-3 mr-1" />
|
||||
<span>Created {format(new Date(org.createdAt), 'MMM d, yyyy')}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
@@ -2,6 +2,7 @@ import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { z } from "zod";
|
||||
import { useAuth } from "@/hooks/use-auth";
|
||||
import { useOrganization } from "@/context/organization-context";
|
||||
import { Redirect } from "wouter";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from "@/components/ui/card";
|
||||
@@ -11,6 +12,7 @@ import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
|
||||
import { ThemeToggle } from "@/components/shared/theme-toggle";
|
||||
import { useTheme } from "@/hooks/use-theme";
|
||||
import { Loader2 } from "lucide-react";
|
||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
|
||||
|
||||
const loginSchema = z.object({
|
||||
username: z.string().min(3, "Username must be at least 3 characters"),
|
||||
@@ -22,6 +24,7 @@ const registerSchema = z.object({
|
||||
email: z.string().email("Please enter a valid email"),
|
||||
password: z.string().min(8, "Password must be at least 8 characters"),
|
||||
fullName: z.string().optional(),
|
||||
organizationId: z.number().optional(),
|
||||
});
|
||||
|
||||
export default function AuthPage() {
|
||||
@@ -43,6 +46,7 @@ export default function AuthPage() {
|
||||
email: "",
|
||||
password: "",
|
||||
fullName: "",
|
||||
organizationId: undefined,
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import { Domain, DnsRecord, Provider } from "@shared/schema";
|
||||
import { Domain, DnsRecord, Provider, Organization } from "@shared/schema";
|
||||
import { MainLayout } from "@/components/layouts/main-layout";
|
||||
import { DomainStatusCard } from "@/components/domain/domain-status-card";
|
||||
import { DomainTable } from "@/components/domain/domain-table";
|
||||
@@ -7,13 +7,14 @@ import { RecentActivity } from "@/components/activity/recent-activity";
|
||||
import { DnsUpdateChart } from "@/components/charts/dns-update-chart";
|
||||
import { ProviderDistributionChart } from "@/components/charts/provider-distribution-chart";
|
||||
import { RecordTypeChart } from "@/components/charts/record-type-chart";
|
||||
import { OrganizationListCard } from "@/components/organization/organization-list-card";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { useOrganization } from "@/context/organization-context";
|
||||
import { Home, CheckCircle, AlertTriangle, AlertCircle, Plus, Wrench, FileText } from "lucide-react";
|
||||
import { Link } from "wouter";
|
||||
|
||||
export default function DashboardPage() {
|
||||
const { currentOrganization } = useOrganization();
|
||||
const { currentOrganization, organizations } = useOrganization();
|
||||
|
||||
// Fetch domains, DNS records, and providers
|
||||
const { data: domains = [] } = useQuery<Domain[]>({
|
||||
@@ -86,6 +87,11 @@ export default function DashboardPage() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Organizations List */}
|
||||
<div className="mb-8">
|
||||
<OrganizationListCard organizations={organizations} />
|
||||
</div>
|
||||
|
||||
{/* Domain Status Table */}
|
||||
<DomainTable />
|
||||
|
||||
|
||||
Reference in New Issue
Block a user