mirror of
https://github.com/kyantech/Palmr.git
synced 2025-10-22 22:02:00 +00:00
refactor(settings): reorganize imports and improve code readability
Restructured imports across multiple files to follow a consistent order and improve readability. Also, adjusted some code formatting for better maintainability.
This commit is contained in:
@@ -1,13 +1,14 @@
|
||||
"use client";
|
||||
|
||||
import { useAppInfo } from "@/contexts/app-info-context";
|
||||
import { removeLogo, uploadLogo } from "@/http/endpoints";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { useTranslations } from "next-intl";
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import { IconCloudUpload, IconTrash } from "@tabler/icons-react";
|
||||
import { useTranslations } from "next-intl";
|
||||
import { toast } from "sonner";
|
||||
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { useAppInfo } from "@/contexts/app-info-context";
|
||||
import { removeLogo, uploadLogo } from "@/http/endpoints";
|
||||
|
||||
interface LogoInputProps {
|
||||
value?: string;
|
||||
onChange: (value: string) => void;
|
||||
@@ -15,7 +16,7 @@ interface LogoInputProps {
|
||||
}
|
||||
|
||||
export function LogoInput({ value, onChange, isDisabled }: LogoInputProps) {
|
||||
const t = useTranslations();
|
||||
const t = useTranslations();
|
||||
const [isUploading, setIsUploading] = useState(false);
|
||||
const [currentLogo, setCurrentLogo] = useState(value);
|
||||
const fileInputRef = useRef<HTMLInputElement>(null);
|
||||
@@ -80,19 +81,9 @@ export function LogoInput({ value, onChange, isDisabled }: LogoInputProps) {
|
||||
{currentLogo ? (
|
||||
<div className="flex flex-col items-center gap-4">
|
||||
<div className="relative max-w-[200px] max-h-[200px] flex">
|
||||
<img
|
||||
alt={t("logo.labels.appLogo")}
|
||||
className="rounded-lg"
|
||||
src={currentLogo}
|
||||
|
||||
sizes="200px"
|
||||
/>
|
||||
<img alt={t("logo.labels.appLogo")} className="rounded-lg" src={currentLogo} sizes="200px" />
|
||||
</div>
|
||||
<Button
|
||||
variant="destructive"
|
||||
disabled={isDisabled}
|
||||
onClick={handleRemoveLogo}
|
||||
>
|
||||
<Button variant="destructive" disabled={isDisabled} onClick={handleRemoveLogo}>
|
||||
{!isUploading && <IconTrash className="mr-2 h-4 w-4" />}
|
||||
{t("logo.buttons.remove")}
|
||||
</Button>
|
||||
|
@@ -1,5 +1,4 @@
|
||||
import { ValidGroup } from "../types";
|
||||
import { SettingsFormProps } from "../types";
|
||||
import { SettingsFormProps, ValidGroup } from "../types";
|
||||
import { SettingsGroup } from "./settings-group";
|
||||
|
||||
const GROUP_ORDER: ValidGroup[] = ["general", "email", "security", "storage"];
|
||||
|
@@ -1,12 +1,13 @@
|
||||
import { createGroupMetadata, createFieldDescriptions } from "../constants";
|
||||
import { SettingsGroupProps } from "../types";
|
||||
import { SettingsInput } from "./settings-input";
|
||||
import React from "react";
|
||||
import { IconChevronDown, IconChevronUp, IconDeviceFloppy } from "@tabler/icons-react";
|
||||
import { useTranslations } from "next-intl";
|
||||
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Card, CardContent, CardHeader } from "@/components/ui/card";
|
||||
import { Separator } from "@/components/ui/separator";
|
||||
import { useTranslations } from "next-intl";
|
||||
import React from "react";
|
||||
import { IconChevronDown, IconChevronUp, IconDeviceFloppy } from "@tabler/icons-react";
|
||||
import { createFieldDescriptions, createGroupMetadata } from "../constants";
|
||||
import { SettingsGroupProps } from "../types";
|
||||
import { SettingsInput } from "./settings-input";
|
||||
|
||||
export function SettingsGroup({ group, configs, form, isCollapsed, onToggleCollapse, onSubmit }: SettingsGroupProps) {
|
||||
const t = useTranslations();
|
||||
@@ -21,7 +22,10 @@ export function SettingsGroup({ group, configs, form, isCollapsed, onToggleColla
|
||||
return (
|
||||
<form onSubmit={form.handleSubmit(onSubmit)}>
|
||||
<Card className="p-6 gap-0">
|
||||
<CardHeader className="flex flex-row items-center justify-between cursor-pointer p-0" onClick={onToggleCollapse}>
|
||||
<CardHeader
|
||||
className="flex flex-row items-center justify-between cursor-pointer p-0"
|
||||
onClick={onToggleCollapse}
|
||||
>
|
||||
<div className="flex flex-row items-center gap-8">
|
||||
{metadata.icon && React.createElement(metadata.icon, { className: "text-xl text-muted-foreground" })}
|
||||
<div className="flex flex-col gap-1">
|
||||
@@ -33,7 +37,11 @@ export function SettingsGroup({ group, configs, form, isCollapsed, onToggleColla
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
{isCollapsed ? <IconChevronDown className="text-muted-foreground" /> : <IconChevronUp className="text-muted-foreground" />}
|
||||
{isCollapsed ? (
|
||||
<IconChevronDown className="text-muted-foreground" />
|
||||
) : (
|
||||
<IconChevronUp className="text-muted-foreground" />
|
||||
)}
|
||||
</CardHeader>
|
||||
<CardContent className={`${isCollapsed ? "hidden" : "block"} px-0`}>
|
||||
<Separator className="my-6" />
|
||||
|
@@ -1,15 +1,15 @@
|
||||
import {
|
||||
Breadcrumb,
|
||||
BreadcrumbItem,
|
||||
import Link from "next/link";
|
||||
import { IconLayoutDashboard, IconSettings } from "@tabler/icons-react";
|
||||
import { useTranslations } from "next-intl";
|
||||
|
||||
import {
|
||||
Breadcrumb,
|
||||
BreadcrumbItem,
|
||||
BreadcrumbLink,
|
||||
BreadcrumbList,
|
||||
BreadcrumbSeparator
|
||||
BreadcrumbSeparator,
|
||||
} from "@/components/ui/breadcrumb";
|
||||
import { Separator } from "@/components/ui/separator";
|
||||
import { useTranslations } from "next-intl";
|
||||
import { IconSettings } from "@tabler/icons-react";
|
||||
import { IconLayoutDashboard } from "@tabler/icons-react";
|
||||
import Link from "next/link";
|
||||
|
||||
export function SettingsHeader() {
|
||||
const t = useTranslations();
|
||||
|
@@ -1,10 +1,10 @@
|
||||
import { useTranslations } from "next-intl";
|
||||
import { UseFormRegister, UseFormWatch } from "react-hook-form";
|
||||
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { createFieldTitles } from "../constants";
|
||||
import { Config } from "../types";
|
||||
import { LogoInput } from "./logo-input";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { UseFormRegister, UseFormWatch } from "react-hook-form";
|
||||
|
||||
|
||||
export interface ConfigInputProps {
|
||||
config: Config;
|
||||
|
@@ -1,25 +1,25 @@
|
||||
import { createTranslator } from 'next-intl';
|
||||
import { IconMail, IconSettings, IconShield, IconDatabase } from '@tabler/icons-react';
|
||||
import { IconDatabase, IconMail, IconSettings, IconShield } from "@tabler/icons-react";
|
||||
import { createTranslator } from "next-intl";
|
||||
|
||||
export const createGroupMetadata = (t: ReturnType<typeof createTranslator>) => ({
|
||||
email: {
|
||||
title: t('settings.groups.email.title'),
|
||||
description: t('settings.groups.email.description'),
|
||||
title: t("settings.groups.email.title"),
|
||||
description: t("settings.groups.email.description"),
|
||||
icon: IconMail,
|
||||
},
|
||||
general: {
|
||||
title: t('settings.groups.general.title'),
|
||||
description: t('settings.groups.general.description'),
|
||||
title: t("settings.groups.general.title"),
|
||||
description: t("settings.groups.general.description"),
|
||||
icon: IconSettings,
|
||||
},
|
||||
security: {
|
||||
title: t('settings.groups.security.title'),
|
||||
description: t('settings.groups.security.description'),
|
||||
title: t("settings.groups.security.title"),
|
||||
description: t("settings.groups.security.description"),
|
||||
icon: IconShield,
|
||||
},
|
||||
storage: {
|
||||
title: t('settings.groups.storage.title'),
|
||||
description: t('settings.groups.storage.description'),
|
||||
title: t("settings.groups.storage.title"),
|
||||
description: t("settings.groups.storage.description"),
|
||||
icon: IconDatabase,
|
||||
},
|
||||
});
|
||||
|
@@ -1,28 +1,25 @@
|
||||
"use client";
|
||||
|
||||
import { ConfigType, GroupFormData } from "../types";
|
||||
import { Config } from "../types";
|
||||
import { useShareContext } from "@/contexts/share-context";
|
||||
import { useAppInfo } from "@/contexts/app-info-context";
|
||||
import { getAllConfigs, bulkUpdateConfigs } from "@/http/endpoints";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { useEffect, useState } from "react";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { useTranslations } from "next-intl";
|
||||
import { useForm } from "react-hook-form";
|
||||
|
||||
import { toast } from "sonner";
|
||||
import { z } from "zod";
|
||||
import { useTranslations } from "next-intl";
|
||||
|
||||
import { useAppInfo } from "@/contexts/app-info-context";
|
||||
import { useShareContext } from "@/contexts/share-context";
|
||||
import { bulkUpdateConfigs, getAllConfigs } from "@/http/endpoints";
|
||||
import { Config, ConfigType, GroupFormData } from "../types";
|
||||
|
||||
const createSchemas = () => ({
|
||||
settingsSchema: z.object({
|
||||
configs: z.record(
|
||||
z.union([z.string(), z.number()]).transform((val) => String(val))
|
||||
),
|
||||
configs: z.record(z.union([z.string(), z.number()]).transform((val) => String(val))),
|
||||
}),
|
||||
});
|
||||
|
||||
export function useSettings() {
|
||||
const t = useTranslations();
|
||||
const t = useTranslations();
|
||||
const { settingsSchema } = createSchemas();
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
const [configs, setConfigs] = useState<Record<string, string>>({});
|
||||
|
@@ -1,4 +1,4 @@
|
||||
"use client"
|
||||
"use client";
|
||||
|
||||
import { ProtectedRoute } from "@/components/auth/protected-route";
|
||||
import { LoadingScreen } from "@/components/layout/loading-screen";
|
||||
@@ -16,7 +16,7 @@ export default function SettingsPage() {
|
||||
}
|
||||
|
||||
return (
|
||||
<ProtectedRoute>
|
||||
<ProtectedRoute requireAdmin>
|
||||
<div className="w-full h-screen flex flex-col">
|
||||
<Navbar />
|
||||
<div className="flex-1 max-w-7xl mx-auto w-full px-6 py-8">
|
||||
|
@@ -5,7 +5,7 @@ import { cva, type VariantProps } from "class-variance-authority";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
const buttonVariants = cva(
|
||||
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
|
||||
"inline-flex items-center cursor-pointer justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
|
||||
{
|
||||
variants: {
|
||||
variant: {
|
||||
|
Reference in New Issue
Block a user