infra: add linting and formatting for js projects (#230)

* wip

* wip

* wip

* format

* wip(mobile): lint and format

* cleanup

* nits

* nits

* idiomatic react

* nit

* format all root files
This commit was merged in pull request #230.
This commit is contained in:
Arjun Patel
2026-06-02 07:44:24 -07:00
committed by GitHub
parent 2fe562ce2b
commit a8a0b7db1b
258 changed files with 7822 additions and 5195 deletions
+46 -37
View File
@@ -1,26 +1,26 @@
import { useEffect, useRef, useState } from "react";
import { useNavigate, useParams, useSearchParams } from "react-router-dom";
import { ArrowLeft, CreditCard, Mail, Shield, Users, X } from "lucide-react";
import { toast } from "sonner";
import { Avatar, AvatarFallback } from "@/components/ui/avatar";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { ScrollArea } from "@/components/ui/scroll-area";
import { Separator } from "@/components/ui/separator";
import { Muted } from "@/components/ui/typography";
import { WindowControls } from "@/components/window-controls";
import { useNetworks } from "@/hooks/use-networks";
import { useEffect, useRef, useState } from 'react';
import { useNavigate, useParams, useSearchParams } from 'react-router-dom';
import { ArrowLeft, CreditCard, Mail, Shield, Users, X } from 'lucide-react';
import { toast } from 'sonner';
import { Avatar, AvatarFallback } from '@/components/ui/avatar';
import { Badge } from '@/components/ui/badge';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { ScrollArea } from '@/components/ui/scroll-area';
import { Separator } from '@/components/ui/separator';
import { Muted } from '@/components/ui/typography';
import { WindowControls } from '@/components/window-controls';
import { useNetworks } from '@/hooks/use-networks';
import {
useNetworkInvitations,
useInviteMembers,
useRevokeInvitation,
useRemoveMember,
} from "@/hooks/use-member-management";
import { useAuthStore } from "@/stores/auth-store";
import { BillingSection } from "@/features/network-billing";
import { ConfirmDestructiveOverlay } from "@/components/confirm-destructive-overlay";
import type { Human } from "@/api/types";
} from '@/hooks/use-member-management';
import { useAuthStore } from '@/stores/auth-store';
import { BillingSection } from '@/features/network-billing';
import { ConfirmDestructiveOverlay } from '@/components/confirm-destructive-overlay';
import type { Human } from '@/api/types';
function MemberRow({
human,
@@ -66,7 +66,7 @@ function MemberRow({
}
function InviteForm({ networkId }: { networkId: string }) {
const [email, setEmail] = useState("");
const [email, setEmail] = useState('');
const inviteMembers = useInviteMembers(networkId);
const handleSubmit = (e: React.FormEvent) => {
@@ -77,7 +77,7 @@ function InviteForm({ networkId }: { networkId: string }) {
inviteMembers.mutate([trimmed], {
onSuccess: () => {
toast.success(`Invitation sent to ${trimmed}`);
setEmail("");
setEmail('');
},
});
};
@@ -96,7 +96,7 @@ function InviteForm({ networkId }: { networkId: string }) {
size="sm"
disabled={!email.trim() || inviteMembers.isPending}
>
{inviteMembers.isPending ? "Sending..." : "Invite"}
{inviteMembers.isPending ? 'Sending...' : 'Invite'}
</Button>
</form>
);
@@ -179,24 +179,30 @@ function Section({ children }: { children: React.ReactNode }) {
export default function NetworkSettingsPage() {
const navigate = useNavigate();
const { networkId } = useParams<{ networkId: string }>();
if (!networkId)
throw new Error('NetworkSettingsPage requires a :networkId route param');
const [searchParams] = useSearchParams();
const { data: networks } = useNetworks();
const network = networks?.find((n) => n.id === networkId);
const { data: invitations, error: invitationsError } = useNetworkInvitations(networkId!);
const { data: invitations, error: invitationsError } =
useNetworkInvitations(networkId);
const currentUser = useAuthStore((s) => s.user);
const isAdmin = currentUser?.id === network?.admin_human.id;
const [memberToRemove, setMemberToRemove] = useState<Human | null>(null);
const removeMember = useRemoveMember(networkId!);
const removeMember = useRemoveMember(networkId);
const billingRef = useRef<HTMLDivElement>(null);
useEffect(() => {
if (searchParams.get("section") === "billing") {
billingRef.current?.scrollIntoView({ behavior: "smooth", block: "start" });
if (searchParams.get('section') === 'billing') {
billingRef.current?.scrollIntoView({
behavior: 'smooth',
block: 'start',
});
}
}, [searchParams]);
const networkName = network?.name ?? "Network";
const networkName = network?.name ?? 'Network';
const memberCount = network?.humans.length ?? 0;
const pendingCount = invitations?.length ?? 0;
const networkInitials = networkName.slice(0, 2).toUpperCase();
@@ -227,8 +233,8 @@ export default function NetworkSettingsPage() {
<div className="min-w-0 flex-1">
<p className="truncate text-base font-semibold">{networkName}</p>
<Muted className="text-xs">
{memberCount} {memberCount === 1 ? "member" : "members"}
{isAdmin ? " · You're an admin" : ""}
{memberCount} {memberCount === 1 ? 'member' : 'members'}
{isAdmin ? " · You're an admin" : ''}
</Muted>
</div>
</div>
@@ -254,7 +260,9 @@ export default function NetworkSettingsPage() {
<MemberRow
human={human}
isAdmin={isRowAdmin}
onRemove={canRemove ? () => setMemberToRemove(human) : undefined}
onRemove={
canRemove ? () => setMemberToRemove(human) : undefined
}
/>
{index < network.humans.length - 1 && (
<Separator className="mx-4" />
@@ -279,7 +287,7 @@ export default function NetworkSettingsPage() {
}
/>
<Separator />
<InviteForm networkId={networkId!} />
<InviteForm networkId={networkId} />
{invitationsError && (
<>
<Separator />
@@ -288,7 +296,7 @@ export default function NetworkSettingsPage() {
</p>
</>
)}
{pendingCount > 0 && (
{invitations && invitations.length > 0 && (
<>
<Separator />
<div className="px-4 pb-1 pt-3">
@@ -296,13 +304,13 @@ export default function NetworkSettingsPage() {
Pending
</Muted>
</div>
{invitations!.map((inv, index) => (
{invitations.map((inv, index) => (
<div key={inv.email}>
<PendingInvitationRow
email={inv.email}
networkId={networkId!}
networkId={networkId}
/>
{index < invitations!.length - 1 && (
{index < invitations.length - 1 && (
<Separator className="mx-4" />
)}
</div>
@@ -319,12 +327,12 @@ export default function NetworkSettingsPage() {
title="Billing"
description={
isAdmin
? "Manage your plan, seats, and payment."
? 'Manage your plan, seats, and payment.'
: "Your network's current plan and usage."
}
/>
<Separator />
<BillingSection networkId={networkId!} />
<BillingSection networkId={networkId} />
</Section>
</div>
@@ -342,7 +350,8 @@ export default function NetworkSettingsPage() {
</li>
<li>Any content they posted stays in the network.</li>
<li>
If they're in a live huddle, they may remain until the call ends.
If they're in a live huddle, they may remain until the call
ends.
</li>
</ul>
}