fix: 🐛 move backend config routes out of appEnv variable

This commit is contained in:
Alexis Gousseau 2026-06-05 12:00:58 +02:00
parent 400c2729dc
commit a0c0f7965a
No known key found for this signature in database
GPG key ID: 7F3C786EE12DBB72
56 changed files with 347 additions and 296 deletions

View file

@ -6,7 +6,7 @@ import { useTheme } from "@/back/providers/ThemeProvider";
import logoUwilSupportLight from "&/images/logos/uwil-support-light.svg";
import logoUwilSupportDark from "&/images/logos/uwil-support-dark.svg";
import logoTinyUwilSupport from "&/images/logos/uwil-support-light-icon.svg";
import { AppEnv } from "@/types/global";
import { ConfigBackend } from "@/back/types/global";
type ApplicationLogoProps = {
forceLight?: boolean;
@ -31,7 +31,7 @@ export default function ApplicationLogo({
forceLight = false,
isCollapsed = false,
}: ApplicationLogoProps) {
const { routes } = usePage().props.appEnv as AppEnv;
const { routes } = usePage().props.configBackend as ConfigBackend;
const { theme } = useTheme();
const wrapperClasses = isCollapsed ? "h-8" : "w-full max-w-[10rem] mx-auto";
const logo = getLogo(isCollapsed, forceLight, theme);

View file

@ -7,12 +7,12 @@ import { useState } from "react";
import BtnOptionnalLinkWithTooltip from "@/back/Components/BtnOptionnalLinkWithTooltip";
import useTrans from "@/hooks/use-translations";
import { useToast } from "@/hooks/use-toast";
import { AuthProp, UserModel } from "@/back/types/global";
import { AppEnv } from "@/types/global";
import { AuthProp, ConfigBackend, UserModel } from "@/back/types/global";
import { GetTranslation } from "@/lib/utils";
export default function BtnResetPassword({ model }: { model: UserModel }) {
const { user: userModel } = usePage().props.auth as AuthProp;
const { routes } = usePage().props.appEnv as AppEnv;
const { routes } = usePage().props.configBackend as ConfigBackend;
const enumUserRole = usePage().props.enumUserRole as UserModel["role"][];
const { toast } = useToast();
@ -73,7 +73,7 @@ export default function BtnResetPassword({ model }: { model: UserModel }) {
)}
</>
}
tooltipContent={useTrans("auth.send_link")}
tooltipContent={GetTranslation("auth.send_link")}
disabled={isSending}
variant="secondary"
size="default"

View file

@ -11,7 +11,12 @@ type Props = {
prefixRoute: string;
};
export default function SwitchFilter({ label, fieldName, modelRoute, prefixRoute }: Props) {
export default function SwitchFilter({
label,
fieldName,
modelRoute,
prefixRoute,
}: Props) {
return (
<SimpleSwitch
name={fieldName}

View file

@ -53,7 +53,7 @@ import useTrans from "@/hooks/use-translations";
import str from "@/hooks/use-string";
import useDeviceType from "@/hooks/use-device-type";
import { cn, GetTranslation } from "@/lib/utils";
import { AppEnv } from "@/types/global";
import { ConfigBackend } from "@/back/types/global";
interface CropValidationRules {
width: number;
@ -95,7 +95,7 @@ export default function ImageCropper({
url,
finalFileName,
}: ImageCropperProps) {
const { routes } = usePage().props.appEnv as AppEnv;
const { routes } = usePage().props.configBackend as ConfigBackend;
const { errors } = usePage().props;
const aspect = 1;

View file

@ -51,7 +51,7 @@ import InputError from "@/back/Components/InputError";
import str from "@/hooks/use-string";
import { cn, GetTranslation } from "@/lib/utils";
import { AppEnv } from "@/types/global";
import { DefaultModel, Paginator } from "@/back/types/global";
import { DefaultModel, Paginator, ConfigBackend } from "@/back/types/global";
/**
* Animation types and configurations
@ -459,7 +459,8 @@ export const ModelSelect = forwardRef<ModelSelectRef, ModelSelectProps>(
field ?? null,
);
const { locale, routes } = usePage().props.appEnv as AppEnv;
const { locale } = usePage().props.appEnv as AppEnv;
const { routes } = usePage().props.configBackend as ConfigBackend;
/**
* Set call ajax.
@ -1223,7 +1224,7 @@ export const ModelSelect = forwardRef<ModelSelectRef, ModelSelectProps>(
"group/button flex rounded-md border min-h-10 h-auto items-center justify-between [&_svg]:pointer-events-auto gap-2 px-4 py-2",
autoSize ? "w-auto" : "w-full",
responsiveSettings.compactMode && "min-h-8 text-sm",
screenSize === "mobile" && "min-h-12 text-base",
screenSize === "mobile" && "min-h-10 text-base",
disabled && "opacity-50 cursor-not-allowed",
{ "border-destructive/50": localErrors[name] },
className,

View file

@ -1034,7 +1034,7 @@ export const MultiSelect = forwardRef<MultiSelectRef, MultiSelectProps>(
"group/button flex rounded-md border min-h-10 h-auto items-center justify-between [&_svg]:pointer-events-auto gap-2 px-4 py-2",
autoSize ? "w-auto" : "w-full",
responsiveSettings.compactMode && "min-h-8 text-sm",
screenSize === "mobile" && "min-h-12 text-base",
screenSize === "mobile" && "min-h-10 text-base",
disabled && "opacity-50 cursor-not-allowed",
className,
)}

View file

@ -32,6 +32,8 @@ import { GetTranslation } from "@/lib/utils";
type ImageProps = {
/** Wysiwyg editor instance. */
editor: Editor;
/** Route name prefix. */
routeName: string;
/** Disable trigger button. */
disabled: boolean;
};
@ -44,7 +46,11 @@ type ImageType = {
height: number;
};
export default function ImageButton({ editor, disabled }: ImageProps) {
export default function ImageButton({
editor,
routeName,
disabled,
}: ImageProps) {
// Get all editor options define with customOptions in the parent SimpleWysiwyg.
const editorOptions = editor.options.editorProps?.attributes as {
[name: string]: string;
@ -247,7 +253,7 @@ export default function ImageButton({ editor, disabled }: ImageProps) {
data.append("tableName", editorOptions.tableName);
// Get wysiwyg image route upload.
const uploadRoute = route("back.wysiwyg.upload");
const uploadRoute = route(`${routeName}wysiwyg.upload`);
try {
const response = await axios.post(uploadRoute, data, {

View file

@ -27,6 +27,7 @@ import { ModelSelect } from "@/back/Components/Inputs/ModelSelect";
import useTrans from "@/hooks/use-translations";
import str from "@/hooks/use-string";
import { AppEnv, LaravelEnum } from "@/types/global";
import { ConfigBackend } from "@/back/types/global";
import { cn, GetTranslation } from "@/lib/utils";
// Custom type with field entry.
@ -75,7 +76,9 @@ type LinkProps = {
export default function LinkButton({ editor, disabled }: LinkProps) {
// Current domain of the projet.
const { url, routes } = usePage().props.appEnv as AppEnv;
const { url } = usePage().props.appEnv as AppEnv;
// Backend configuration.
const { routes } = usePage().props.configBackend as ConfigBackend;
// All models from global enum.
const enumModelsList = usePage().props.enumModelsList as LaravelEnumWithField;

View file

@ -24,6 +24,7 @@ import InputError from "@/back/Components/InputError";
import WordCounter from "@/back/Components/WordCounter";
import Toolbar from "@/back/Components/Inputs/Wysiwyg/Toolbar";
import { cn, GetTranslation } from "@/lib/utils";
import { ConfigBackend } from "@/back/types/global";
type SimpleWysiwygProps = {
className?: string;
@ -55,6 +56,8 @@ export default function SimpleWysiwyg({
parentErrors = null,
setData,
}: SimpleWysiwygProps) {
const routeName = (usePage().props.configBackend as ConfigBackend).routes
.name;
const { errors } = usePage().props;
const localErrors = parentErrors ?? errors;
@ -171,7 +174,7 @@ export default function SimpleWysiwyg({
"border-destructive/50": localErrors[name],
})}
>
<Toolbar editor={editor} />
<Toolbar editor={editor} routeName={routeName} />
<EditorContent
id={id}
editor={editor}

View file

@ -54,9 +54,10 @@ type AllowedAlignements = "left" | "center" | "right" | "justify";
type ToolbarProps = {
editor: Editor;
routeName: string;
};
export default function Toolbar({ editor }: ToolbarProps) {
export default function Toolbar({ editor, routeName }: ToolbarProps) {
const [, forceUpdate] = useState<number>(0);
const [docSelected, setDocSelected] = useState<boolean>(false);
const [headerHeight, setHeaderHeight] = useState<number>(0);
@ -435,7 +436,11 @@ export default function Toolbar({ editor }: ToolbarProps) {
size="icon"
/>
<TableButton editor={editor} disabled={docSelected} />
<ImageButton editor={editor} disabled={docSelected} />
<ImageButton
editor={editor}
routeName={routeName}
disabled={docSelected}
/>
<LinkButton editor={editor} disabled={docSelected} />
<Separator orientation="vertical" className="!h-auto" />
<BtnOptionnalLinkWithTooltip

View file

@ -15,13 +15,12 @@ import AppBreadcrumbs from "@/back/Components/Layout/AppBreadcrumbs";
import AppSettings from "@/back/Components/Layout/Settings/AppSettings";
import CustomSidebarTrigger from "@/back/Components/CustomSidebarTrigger";
import { Button } from "@/components/ui/button";
import { AuthProp } from "@/back/types/global";
import { AuthProp, ConfigBackend } from "@/back/types/global";
import useTrans from "@/hooks/use-translations";
import { AppEnv } from "@/types/global";
export default function AppHeader() {
const { user } = usePage().props.auth as AuthProp;
const { routes } = usePage().props.appEnv as AppEnv;
const { routes } = usePage().props.configBackend as ConfigBackend;
return (
<header className="sticky top-0 flex flex-col justify-between items-center bg-background border-b z-20">
<div className="sticky top-0 flex flex-row justify-between items-center w-full py-4">

View file

@ -12,6 +12,7 @@ import {
// * Other
import SettingRegistry from "@/back/Components/Layout/Settings/SettingRegistry";
import { cn, GetTranslation } from "@/lib/utils";
import { ConfigBackend } from "@/back/types/global";
import { AppEnv } from "@/types/global";
type AppSettingsProps = {
@ -19,7 +20,10 @@ type AppSettingsProps = {
};
export default function AppSettings({ className = "" }: AppSettingsProps) {
const appEnv = usePage().props.appEnv as AppEnv;
const { appEnv, configBackend } = usePage().props as unknown as {
appEnv: AppEnv;
configBackend: ConfigBackend;
};
return (
<div className={cn(className)}>
<DropdownMenu>
@ -32,12 +36,14 @@ export default function AppSettings({ className = "" }: AppSettingsProps) {
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent side="bottom" className="w-fit me-1">
{SettingRegistry.getAll(appEnv).map((Section, index, arr) => (
<>
{Section}
{Section && index < arr.length - 1 && <DropdownMenuSeparator />}
</>
))}
{SettingRegistry.getAll(appEnv, configBackend).map(
(Section, index, arr) => (
<>
{Section}
{Section && index < arr.length - 1 && <DropdownMenuSeparator />}
</>
),
)}
</DropdownMenuContent>
</DropdownMenu>
</div>

View file

@ -9,9 +9,14 @@ import { DropdownMenuItem } from "@/components/ui/dropdown-menu";
import { AppEnv } from "@/types/global";
import useTrans from "@/hooks/use-translations";
import { cn } from "@/lib/utils";
import { ConfigBackend } from "@/back/types/global";
export default function Languages(appEnv: AppEnv) {
const { locales, locale, routes } = appEnv;
export default function Languages(
appEnv: AppEnv,
configBackend: ConfigBackend,
) {
const { locales, locale } = appEnv;
const { routes } = configBackend;
const { post, setData } = useForm({
lang: "system",
});

View file

@ -1,10 +1,15 @@
// * Packages
import { ReactNode } from "react";
// * Other
import { ConfigBackend } from "@/back/types/global";
import { AppEnv } from "@/types/global";
// eslint-disable-next-line no-unused-vars
type SettingResolver = (appEnv: AppEnv) => ReactNode;
/* eslint-disable no-unused-vars */
type SettingResolver = (
appEnv: AppEnv,
configBackend: ConfigBackend,
) => ReactNode;
/* eslint-enable no-unused-vars */
export default class SettingRegistry {
private static resolvers: SettingResolver[] = [];
@ -13,8 +18,8 @@ export default class SettingRegistry {
this.resolvers.push(resolver);
}
static getAll(appEnv: AppEnv): ReactNode[] {
return this.resolvers.map((resolver) => resolver(appEnv));
static getAll(appEnv: AppEnv, configBackend: ConfigBackend): ReactNode[] {
return this.resolvers.map((resolver) => resolver(appEnv, configBackend));
}
}
@ -26,7 +31,7 @@ const modules = import.meta.glob("./Sections/*.tsx", {
string,
{
// eslint-disable-next-line no-unused-vars
default: (appEnv: AppEnv) => ReactNode;
default: (appEnv: AppEnv, configBackend: ConfigBackend) => ReactNode;
}
>;

View file

@ -45,9 +45,9 @@ import { SidebarRegistry } from "@/back/Components/Layout/Sidebar/SidebarRegistr
import Views from "@/back/lib/actions";
import str from "@/hooks/use-string";
import useTrans from "@/hooks/use-translations";
import { AppEnv } from "@/types/global";
import { AuthProp, UserModel } from "@/back/types/global";
import { AuthProp, UserModel, ConfigBackend } from "@/back/types/global";
import { GetTranslation } from "@/lib/utils";
import { AppEnv } from "@/types/global";
export type NavListLinksProps = {
/** Title of the button. */
@ -85,12 +85,12 @@ export type NavListProps = Array<{
*/
export const filterActions = ({
auth,
appEnv,
configBackend,
items,
model,
}: {
auth: AuthProp;
appEnv: AppEnv;
configBackend: ConfigBackend;
items?: ReactNode[];
model?: string;
}): ReactNode => {
@ -108,7 +108,7 @@ export const filterActions = ({
<DropdownMenuItem key="create" className="p-0">
<Button variant="ghost" asChild>
<Link
href={route(`${appEnv.routes.name}${model}.create`)}
href={route(`${configBackend.routes.name}${model}.create`)}
className="w-full"
>
{/* eslint-disable-next-line react/jsx-pascal-case */}
@ -125,9 +125,11 @@ export const filterActions = ({
};
export default function AppSidebar() {
const { appEnv, auth, enumUserRole } = usePage().props as unknown as {
const { appEnv, auth, configBackend, enumUserRole } = usePage()
.props as unknown as {
appEnv: AppEnv;
auth: AuthProp;
configBackend: ConfigBackend;
enumUserRole: UserModel["role"][];
};
const { state } = useSidebar();
@ -153,19 +155,19 @@ export default function AppSidebar() {
show: true,
icon: HomeIcon,
},
...SidebarRegistry.getAll(auth, appEnv, "pages"),
...SidebarRegistry.getAll(auth, configBackend, "pages"),
],
},
{
title: transModules,
show: SidebarRegistry.getAll(auth, appEnv, "modules").length > 0,
links: SidebarRegistry.getAll(auth, appEnv, "modules"),
show: SidebarRegistry.getAll(auth, configBackend, "modules").length > 0,
links: SidebarRegistry.getAll(auth, configBackend, "modules"),
},
{
title: str(transAdmin).plural().value(),
show: auth.user.role.value === isConceptor!.value,
links: [
...SidebarRegistry.getAll(auth, appEnv, "admin"),
...SidebarRegistry.getAll(auth, configBackend, "admin"),
{
title: transTelescope,
link: route().has("telescope") ? route("telescope") : undefined,
@ -222,7 +224,7 @@ export default function AppSidebar() {
.map((navLink) => {
const isActive =
route().current(
`${appEnv.routes.name}${navLink.model}.*`,
`${configBackend.routes.name}${navLink.model}.*`,
) || navLink.activeCondition?.some(Boolean);
const sidebarButton = (
<SidebarMenuButton
@ -245,7 +247,7 @@ export default function AppSidebar() {
) : (
<Link
href={route(
`${appEnv.routes.name}${navLink.model}.index`,
`${configBackend.routes.name}${navLink.model}.index`,
)}
className="bg-transparent"
>

View file

@ -11,19 +11,18 @@ import {
NavListLinksProps,
} from "@/back/Components/Layout/Sidebar/AppSidebar";
import { SidebarGroupLink } from "@/back/Components/Layout/Sidebar/SidebarRegistry";
import { AuthProp } from "@/back/types/global";
import { AuthProp, ConfigBackend } from "@/back/types/global";
import str from "@/hooks/use-string";
import { GetTranslation } from "@/lib/utils";
import useTrans from "@/hooks/use-translations";
import Views from "@/back/lib/actions";
import { AppEnv } from "@/types/global";
export default function SidebarLinkBrands(
auth: AuthProp,
appEnv: AppEnv,
configBackend: ConfigBackend,
): SidebarGroupLink {
const modelName = "brands";
const routeName = appEnv.routes.name;
const routeName = configBackend.routes.name;
// Translations.
const transModel = GetTranslation(`models.classes.${modelName}`, {
@ -46,7 +45,7 @@ export default function SidebarLinkBrands(
actions: (model: string) =>
filterActions({
auth,
appEnv,
configBackend,
model,
items: [
auth.policies.brands.create && (

View file

@ -11,19 +11,18 @@ import {
NavListLinksProps,
} from "@/back/Components/Layout/Sidebar/AppSidebar";
import { SidebarGroupLink } from "@/back/Components/Layout/Sidebar/SidebarRegistry";
import { AuthProp } from "@/back/types/global";
import { AuthProp, ConfigBackend } from "@/back/types/global";
import str from "@/hooks/use-string";
import { GetTranslation } from "@/lib/utils";
import useTrans from "@/hooks/use-translations";
import Views from "@/back/lib/actions";
import { AppEnv } from "@/types/global";
export default function SidebarLinkInvoiceCompanies(
auth: AuthProp,
appEnv: AppEnv,
configBackend: ConfigBackend,
): SidebarGroupLink {
const modelName = "invoice-companies";
const routeName = appEnv.routes.name;
const routeName = configBackend.routes.name;
// Translations.
const transModel = GetTranslation(`models.classes.${modelName}`, {
@ -46,7 +45,7 @@ export default function SidebarLinkInvoiceCompanies(
actions: (model: string) =>
filterActions({
auth,
appEnv,
configBackend,
model,
items: [
auth.policies.invoiceCompanies.create && (

View file

@ -11,19 +11,18 @@ import {
NavListLinksProps,
} from "@/back/Components/Layout/Sidebar/AppSidebar";
import { SidebarGroupLink } from "@/back/Components/Layout/Sidebar/SidebarRegistry";
import { AuthProp } from "@/back/types/global";
import { AuthProp, ConfigBackend } from "@/back/types/global";
import str from "@/hooks/use-string";
import { GetTranslation } from "@/lib/utils";
import useTrans from "@/hooks/use-translations";
import Views from "@/back/lib/actions";
import { AppEnv } from "@/types/global";
export default function SidebarLinkInvoicePackages(
auth: AuthProp,
appEnv: AppEnv,
configBackend: ConfigBackend,
): SidebarGroupLink {
const modelName = "invoice-packages";
const routeName = appEnv.routes.name;
const routeName = configBackend.routes.name;
// Translations.
const transModel = GetTranslation(`models.classes.${modelName}`, {
@ -46,7 +45,7 @@ export default function SidebarLinkInvoicePackages(
actions: (model: string) =>
filterActions({
auth,
appEnv,
configBackend,
model,
items: [
auth.policies.invoicePackages.create && (

View file

@ -11,19 +11,18 @@ import {
NavListLinksProps,
} from "@/back/Components/Layout/Sidebar/AppSidebar";
import { SidebarGroupLink } from "@/back/Components/Layout/Sidebar/SidebarRegistry";
import { AuthProp } from "@/back/types/global";
import { AuthProp, ConfigBackend } from "@/back/types/global";
import str from "@/hooks/use-string";
import { GetTranslation } from "@/lib/utils";
import useTrans from "@/hooks/use-translations";
import Views from "@/back/lib/actions";
import { AppEnv } from "@/types/global";
export default function SidebarLinkNotices(
auth: AuthProp,
appEnv: AppEnv,
configBackend: ConfigBackend,
): SidebarGroupLink {
const modelName = "notices";
const routeName = appEnv.routes.name;
const routeName = configBackend.routes.name;
// Translations.
const transModel = GetTranslation(`models.classes.${modelName}`, {
@ -46,7 +45,7 @@ export default function SidebarLinkNotices(
actions: (model: string) =>
filterActions({
auth,
appEnv,
configBackend,
model,
items: [
auth.policies.notices.create && (

View file

@ -11,19 +11,18 @@ import {
NavListLinksProps,
} from "@/back/Components/Layout/Sidebar/AppSidebar";
import { SidebarGroupLink } from "@/back/Components/Layout/Sidebar/SidebarRegistry";
import { AuthProp } from "@/back/types/global";
import { AuthProp, ConfigBackend } from "@/back/types/global";
import str from "@/hooks/use-string";
import { GetTranslation } from "@/lib/utils";
import useTrans from "@/hooks/use-translations";
import Views from "@/back/lib/actions";
import { AppEnv } from "@/types/global";
export default function SidebarLinkSites(
auth: AuthProp,
appEnv: AppEnv,
configBackend: ConfigBackend,
): SidebarGroupLink {
const modelName = "sites";
const routeName = appEnv.routes.name;
const routeName = configBackend.routes.name;
// Translations.
const transModel = GetTranslation(`models.classes.${modelName}`, {
@ -46,7 +45,7 @@ export default function SidebarLinkSites(
actions: (model: string) =>
filterActions({
auth,
appEnv,
configBackend,
model,
items: [
auth.policies.sites.create && (

View file

@ -6,14 +6,13 @@ import {
NavListLinksProps,
} from "@/back/Components/Layout/Sidebar/AppSidebar";
import { SidebarGroupLink } from "@/back/Components/Layout/Sidebar/SidebarRegistry";
import { AuthProp } from "@/back/types/global";
import { AuthProp, ConfigBackend } from "@/back/types/global";
import str from "@/hooks/use-string";
import { GetTranslation } from "@/lib/utils";
import { AppEnv } from "@/types/global";
export default function Users(
auth: AuthProp,
appEnv: AppEnv,
configBackend: ConfigBackend,
): SidebarGroupLink {
const modelName = "users";
const transUsers = GetTranslation(
@ -28,7 +27,7 @@ export default function Users(
model: modelName,
icon: UsersIcon,
show: auth.policies.users.viewAny,
actions: (model: string) => filterActions({ auth, appEnv, model }),
actions: (model: string) => filterActions({ auth, configBackend, model }),
};
return { link, group: "admin" };

View file

@ -1,6 +1,5 @@
import { NavListLinksProps } from "@/back/Components/Layout/Sidebar/AppSidebar";
import { AuthProp } from "@/back/types/global";
import { AppEnv } from "@/types/global";
import { AuthProp, ConfigBackend } from "@/back/types/global";
export type SidebarGroupType = "pages" | "admin" | "modules";
@ -9,8 +8,12 @@ export type SidebarGroupLink = {
group: SidebarGroupType;
};
// eslint-disable-next-line no-unused-vars
export type LinkResolver = (auth: AuthProp, appEnv: AppEnv) => SidebarGroupLink;
/* eslint-disable no-unused-vars */
export type LinkResolver = (
auth: AuthProp,
configBackend: ConfigBackend,
) => SidebarGroupLink;
/* eslint-enable no-unused-vars */
export class SidebarRegistry {
private static resolvers: LinkResolver[] = [];
@ -21,11 +24,11 @@ export class SidebarRegistry {
static getAll(
auth: AuthProp,
appEnv: AppEnv,
configBackend: ConfigBackend,
group: SidebarGroupType,
): NavListLinksProps[] {
return this.resolvers
.map((resolver) => resolver(auth, appEnv))
.map((resolver) => resolver(auth, configBackend))
.filter((sidebarGroupLink) => sidebarGroupLink.group === group)
.sort((a, b) =>
a.link.title.localeCompare(b.link.title, undefined, {
@ -44,7 +47,7 @@ const modules = import.meta.glob("./Links/*.tsx", {
string,
{
// eslint-disable-next-line no-unused-vars
default: (auth: AuthProp, appEnv: AppEnv) => SidebarGroupLink;
default: (auth: AuthProp, configBackend: ConfigBackend) => SidebarGroupLink;
}
>;

View file

@ -28,10 +28,13 @@ import { useFormatedDate } from "@/hooks/use-formated-value";
import { useToast } from "@/hooks/use-toast";
import useTrans from "@/hooks/use-translations";
import str from "@/hooks/use-string";
import { DefaultModel, Views as ViewsType } from "@/back/types/global";
import {
DefaultModel,
Views as ViewsType,
ConfigBackend,
} from "@/back/types/global";
import Views from "@/back/lib/actions";
import { ToastActionElement, ToastProps } from "@/components/ui/toast";
import { AppEnv } from "@/types/global";
interface Translations {
successfulArchivation: string;
@ -71,7 +74,7 @@ function GetAction({
action: ViewsType[number];
modelRoute: string;
model: DefaultModel;
routes: AppEnv["routes"];
routes: ConfigBackend["routes"];
}) {
return (
<Button asChild variant="ghost" className="w-full">
@ -205,7 +208,8 @@ function PostAction({
setOpen: (value: boolean) => void;
}) {
const { delete: destroy, patch } = useForm();
const { name: nameRoute } = (usePage().props.appEnv as AppEnv).routes;
const { name: nameRoute } = (usePage().props.configBackend as ConfigBackend)
.routes;
const isRestoreAction = action.label === Views.RESTORATION.label;
const isArchiveAction = action.label === Views.ARCHIVATION.label;
@ -337,7 +341,7 @@ export default function ModelActions({
inDialog = false,
message = "uwil-backend::back.model_action_updated_at",
}: ModelActionsProps) {
const { routes } = usePage().props.appEnv as AppEnv;
const { routes } = usePage().props.configBackend as ConfigBackend;
const [open, setOpen] = useState(false);
const messageTrans = useTrans(message);
const formattedDate = useFormatedDate(modelUpdatedAt);

View file

@ -42,7 +42,6 @@ export default function DataTableSearch({
isArchiveRoute,
});
};
const onDeleteSearch = () => {
setSearch(null);
const params = {
@ -56,7 +55,6 @@ export default function DataTableSearch({
isArchiveRoute,
});
};
return (
<>
<form

View file

@ -1,6 +1,8 @@
// * Packages
import { FileTextIcon, UserIcon } from "lucide-react";
import { route } from "ziggy-js";
import { Row } from "@tanstack/react-table";
import { usePage } from "@inertiajs/react";
// * Components shadcn
import { Badge } from "@/components/ui/badge";
// * Other
@ -11,13 +13,10 @@ import DataTableFilterButton from "@/back/Components/Table/DataTableFilterButton
import BtnOptionnalLinkWithTooltip from "@/back/Components/BtnOptionnalLinkWithTooltip";
import { GetFormatedDate, GetTranslation } from "@/lib/utils";
import { Views } from "@/back/lib/actions";
import { Resource } from "@/back/types/global";
import { ConfigBackend, Resource } from "@/back/types/global";
import { ActivityLogModel } from "@/back/types/activity-logs";
import str from "@/hooks/use-string";
import useTrans from "@/hooks/use-translations";
import { Row } from "@tanstack/react-table";
import { usePage } from "@inertiajs/react";
import { AppEnv } from "@/types/global";
type ActivityLogsEventEnumProps = Record<
string,
@ -149,14 +148,15 @@ const getColumns = (
const modelSplit = modelClass.split("\\");
const modelTargetName = modelSplit[modelSplit.length - 1];
const model = str(modelTargetName).kebabCase().value();
const targetRoute = `${routeName}${str(model).plural().value()}.show`;
if (event !== activityLogsEventEnum.deleted.value) {
if (
event !== activityLogsEventEnum.deleted.value &&
route().has(targetRoute)
) {
return (
<BtnOptionnalLinkWithTooltip
link={route(
`${routeName}${str(model).plural().value()}.show`,
modelId,
)}
link={route(targetRoute, modelId)}
content={
<>
<FileTextIcon />
@ -209,11 +209,11 @@ export default function Index({
searchFields,
activityLogsEventEnum,
}: ActivityLogsIndexProps) {
const routeName = (usePage().props.appEnv as AppEnv).routes.name;
const routeName = (usePage().props.configBackend as ConfigBackend).routes
.name;
const modelName = usePage().props.modelName as string;
const columns = getColumns(routeName, activityLogsEventEnum);
const actionModels = [Views.VISUALIZATION];
return (
<AuthenticatedLayout
title={str(
@ -224,7 +224,11 @@ export default function Index({
.ucFirst()
.value()}
>
<DataTableSearch modelRoute={modelName} searchFields={searchFields} />
<DataTableSearch
modelRoute={modelName}
prefixRoute={routeName}
searchFields={searchFields}
/>
<DataTable
columns={columns}
modelRoute={modelName}

View file

@ -9,12 +9,11 @@ import AuthenticatedLayout from "@/back/Layouts/AuthenticatedLayout";
import DetailsTable from "@/back/Components/Table/DetailsTable";
import ModelActions from "@/back/Components/ModelActions";
import BtnOptionnalLinkWithTooltip from "@/back/Components/BtnOptionnalLinkWithTooltip";
import { AuthProp, SingleResource } from "@/back/types/global";
import { AuthProp, ConfigBackend, SingleResource } from "@/back/types/global";
import { ActivityLogModel } from "@/back/types/activity-logs";
import str from "@/hooks/use-string";
import useTrans from "@/hooks/use-translations";
import { GetFormatedDate, GetTranslation } from "@/lib/utils";
import { AppEnv } from "@/types/global";
type ActivityLogsEventEnumProps = Record<
string,
@ -112,10 +111,12 @@ const getColumns = (
const modelSplit = value.split("\\");
const modelTargetName = modelSplit[modelSplit.length - 1];
const model = str(modelTargetName).kebabCase().plural().value();
return activityLogModel.event !==
activityLogsEventEnum.deleted.value ? (
const targetRoute = `${routeName}${model}.show`;
return activityLogModel.event !== activityLogsEventEnum.deleted.value &&
route().has(targetRoute) ? (
<BtnOptionnalLinkWithTooltip
link={route(`${routeName}${model}.show`, activityLogModel.model_id)}
link={route(targetRoute, activityLogModel.model_id)}
content={
<>
<UserIcon />
@ -184,15 +185,15 @@ export default function Show({
data,
activityLogsEventEnum,
}: ActivityLogsShowProps) {
const { auth, appEnv } = usePage().props as unknown as {
const { auth, configBackend } = usePage().props as unknown as {
auth: AuthProp;
appEnv: AppEnv;
configBackend: ConfigBackend;
};
const { viewAny } = auth.policies.activityLogs;
const modelName = usePage().props.modelName as string;
const activityLogModel = data.data as ActivityLogModel;
const activityLogModel = data.data as unknown as ActivityLogModel;
const columns = getColumns(
appEnv.routes.name,
configBackend.routes.name,
activityLogModel,
activityLogsEventEnum,
);
@ -202,7 +203,7 @@ export default function Show({
viewAny && (
<div className="flex justify-end items-center gap-x-1.5">
<BtnOptionnalLinkWithTooltip
link={route(`${appEnv.routes.name}${modelName}.index`)}
link={route(`${configBackend.routes.name}${modelName}.index`)}
content={<ArrowLeftIcon />}
tooltipContent={<p>{transBackToList}</p>}
/>

View file

@ -16,10 +16,11 @@ import GuestLayout from "@/back/Layouts/GuestLayout";
import SimpleString from "@/back/Components/Inputs/SimpleString";
import useTrans from "@/hooks/use-translations";
import { toast } from "@/hooks/use-toast";
import { AppEnv } from "@/types/global";
import { ConfigBackend } from "@/back/types/global";
export default function ForgotPassword() {
const routeName = (usePage().props.appEnv as AppEnv).routes.name;
const routeName = (usePage().props.configBackend as ConfigBackend).routes
.name;
const { post, setData, data, processing } = useForm({
email: "",

View file

@ -15,12 +15,16 @@ import {
import GuestLayout from "@/back/Layouts/GuestLayout";
import SimpleString from "@/back/Components/Inputs/SimpleString";
import useTrans from "@/hooks/use-translations";
import { AppEnv } from "@/types/global";
import { toast } from "@/hooks/use-toast";
import SimpleSwitch from "@/back/Components/Inputs/SimpleSwitch";
import { ConfigBackend } from "@/back/types/global";
import { AppEnv } from "@/types/global";
export default function Login() {
const appEnv = usePage().props.appEnv as AppEnv;
const { appEnv, configBackend } = usePage().props as unknown as {
appEnv: AppEnv;
configBackend: ConfigBackend;
};
/** Translations. */
const transConnected = useTrans("auth.connected");
@ -35,7 +39,7 @@ export default function Login() {
const submit = (event: SubmitEvent) => {
event.preventDefault();
post(route(`${appEnv.routes.name}login.post`), {
post(route(`${configBackend.routes.name}login.post`), {
onSuccess: () => {
toast({
title: transConnected,
@ -104,7 +108,7 @@ export default function Login() {
</div>
<div className="flex flex-row items-center justify-between gap-y-3">
<Link
href={route(`${appEnv.routes.name}forgot-password`)}
href={route(`${configBackend.routes.name}forgot-password`)}
className="flex justify-center items-center gap-1 rounded-md text-sm text-gray-600 underline hover:text-gray-900 focus:outline-none focus:ring-2 focus:ring-primary focus:ring-offset-2"
>
{useTrans("auth.forgot_password")}

View file

@ -16,7 +16,7 @@ import GuestLayout from "@/back/Layouts/GuestLayout";
import SimpleString from "@/back/Components/Inputs/SimpleString";
import useTrans from "@/hooks/use-translations";
import { toast } from "@/hooks/use-toast";
import { AppEnv } from "@/types/global";
import { ConfigBackend } from "@/back/types/global";
type ResetPasswordProps = {
token: string;
@ -24,7 +24,8 @@ type ResetPasswordProps = {
};
export default function ResetPassword({ token, email }: ResetPasswordProps) {
const routeName = (usePage().props.appEnv as AppEnv).routes.name;
const routeName = (usePage().props.configBackend as ConfigBackend).routes
.name;
const resetSent = useTrans("auth.reset_sent");
const resetSentDesc = useTrans("auth.reset_sent_desc");

View file

@ -8,9 +8,8 @@ import Form from "@/back/Pages/Brands/Form";
import BtnOptionnalLinkWithTooltip from "@/back/Components/BtnOptionnalLinkWithTooltip";
import useTrans from "@/hooks/use-translations";
import { Actions, Methods } from "@/back/lib/enums";
import { AuthProp, SingleResource } from "@/back/types/global";
import { AuthProp, ConfigBackend, SingleResource } from "@/back/types/global";
import { BrandModel } from "@/back/types/project";
import { AppEnv } from "@/types/global";
export default function Create({
data,
@ -19,7 +18,8 @@ export default function Create({
data: SingleResource;
modelName: string;
}) {
const routeName = (usePage().props.appEnv as AppEnv).routes.name;
const routeName = (usePage().props.configBackend as ConfigBackend).routes
.name;
const { viewAny } = (usePage().props.auth as AuthProp).policies.brands;
const model = data.data as BrandModel;

View file

@ -10,9 +10,8 @@ import Form from "@/back/Pages/Brands/Form";
import useTrans from "@/hooks/use-translations";
import { Actions, Methods } from "@/back/lib/enums";
import { Views } from "@/back/lib/actions";
import { AuthProp, SingleResource } from "@/back/types/global";
import { AuthProp, ConfigBackend, SingleResource } from "@/back/types/global";
import { BrandModel } from "@/back/types/project";
import { AppEnv } from "@/types/global";
export default function Edit({
data,
@ -21,7 +20,8 @@ export default function Edit({
data: SingleResource;
modelName: string;
}) {
const routeName = (usePage().props.appEnv as AppEnv).routes.name;
const routeName = (usePage().props.configBackend as ConfigBackend).routes
.name;
const { viewAny } = (usePage().props.auth as AuthProp).policies.brands;
const model = data.data as BrandModel;
const actionModels = [

View file

@ -14,12 +14,11 @@ import SoftdeleteWarning from "@/back/Components/SoftdeleteWarning";
import BtnOptionnalLinkWithTooltip from "@/back/Components/BtnOptionnalLinkWithTooltip";
import { GetFormatedDate, GetTranslation } from "@/lib/utils";
import { Views } from "@/back/lib/actions";
import { AuthProp, Resource } from "@/back/types/global";
import { AuthProp, ConfigBackend, Resource } from "@/back/types/global";
import str from "@/hooks/use-string";
import useTrans from "@/hooks/use-translations";
import RenderTranslationCell from "@/back/Components/Table/RenderTranslationCell";
import { BrandModel } from "@/back/types/project";
import { AppEnv } from "@/types/global";
const getColumns = () => {
return [
@ -67,12 +66,12 @@ export default function Index({
searchFields: string;
modelName: string;
}) {
const { auth, appEnv } = usePage().props as unknown as {
const { auth, configBackend } = usePage().props as unknown as {
auth: AuthProp;
appEnv: AppEnv;
configBackend: ConfigBackend;
};
const { viewAny, viewTrash, create } = auth.policies.brands;
const routeName = appEnv.routes.name;
const routeName = configBackend.routes.name;
const isArchiveRoute = route().current(`${routeName}${modelName}.trash`);
const actionModels = isArchiveRoute
? [Views.RESTORATION, Views.FORCEDELETION]

View file

@ -16,7 +16,7 @@ import ModelActions from "@/back/Components/ModelActions";
import BtnOptionnalLinkWithTooltip from "@/back/Components/BtnOptionnalLinkWithTooltip";
import { GetFormatedDate, GetTranslation } from "@/lib/utils";
import { Views } from "@/back/lib/actions";
import { AuthProp, SingleResource } from "@/back/types/global";
import { AuthProp, ConfigBackend, SingleResource } from "@/back/types/global";
import str from "@/hooks/use-string";
import useTrans from "@/hooks/use-translations";
import { TranslationField } from "@/back/types/i18n";
@ -24,7 +24,11 @@ import RenderTranslationCell from "@/back/Components/Table/RenderTranslationCell
import { BrandModel, SiteModel } from "@/back/types/project";
import { AppEnv } from "@/types/global";
const getColumns = (appEnv: AppEnv, viewAnySites: boolean) => {
const getColumns = (
locale: AppEnv["locale"],
routeName: string,
viewAnySites: boolean,
) => {
return [
{
accessorKey: "name",
@ -41,7 +45,7 @@ const getColumns = (appEnv: AppEnv, viewAnySites: boolean) => {
cell: ({ value }: { value: Array<SiteModel> }) => {
if (value.length) {
const projectData = (siteModel: SiteModel) => (
<span>{siteModel.name[appEnv.locale]}</span>
<span>{siteModel.name[locale]}</span>
);
return (
<div className="flex flex-row flex-wrap justify-start items-center gap-1.5">
@ -81,7 +85,7 @@ const getColumns = (appEnv: AppEnv, viewAnySites: boolean) => {
if (viewAnySites && siteModel.deleted_at === null) {
content = (
<BtnOptionnalLinkWithTooltip
link={route(`${appEnv.routes.name}sites.show`, siteModel)}
link={route(`${routeName}sites.show`, siteModel)}
content={
<>
<GlobeIcon />
@ -164,12 +168,14 @@ export default function Show({
data: SingleResource;
modelName: string;
}) {
const { auth, appEnv } = usePage().props as unknown as {
const { auth, appEnv, configBackend } = usePage().props as unknown as {
auth: AuthProp;
appEnv: AppEnv;
configBackend: ConfigBackend;
};
const { viewAny } = auth.policies.brands;
const { viewAny: viewAnySites } = auth.policies.sites;
const routeName = configBackend.routes.name;
const model = data.data as BrandModel;
const actionModels = [Views.EDITION, Views.DUPLICATION, Views.ARCHIVATION];
const transTitle = useTrans(
@ -182,7 +188,7 @@ export default function Show({
},
},
);
const columns = getColumns(appEnv, viewAnySites);
const columns = getColumns(appEnv.locale, routeName, viewAnySites);
// Translations.
const transCrudBackToList = useTrans("uwil-backend::back.crud_back_to_list");
@ -192,7 +198,7 @@ export default function Show({
viewAny && (
<div className="flex justify-end items-center gap-x-1.5">
<BtnOptionnalLinkWithTooltip
link={route(`${appEnv.routes.name}${modelName}.index`)}
link={route(`${routeName}${modelName}.index`)}
content={<ArrowLeftIcon />}
tooltipContent={<p>{transCrudBackToList}</p>}
/>

View file

@ -9,11 +9,12 @@ import { ThemeProvider } from "@/back/providers/ThemeProvider";
import AppFooter from "@/back/Components/Layout/AppFooter";
import ApplicationLogo from "@/back/Components/ApplicationLogo";
import useTrans from "@/hooks/use-translations";
import { AppEnv } from "@/types/global";
import { ConfigBackend } from "@/back/types/global";
import { GetTranslation } from "@/lib/utils";
export default function Default({ status }: { status: number }) {
const routeName = (usePage().props.appEnv as AppEnv).routes.name;
const routeName = (usePage().props.configBackend as ConfigBackend).routes
.name;
return (
<ThemeProvider defaultTheme="light" storageKey="vite-ui-theme">
<TooltipProvider>

View file

@ -8,9 +8,8 @@ import Form from "@/back/Pages/InvoiceCompanies/Form";
import BtnOptionnalLinkWithTooltip from "@/back/Components/BtnOptionnalLinkWithTooltip";
import useTrans from "@/hooks/use-translations";
import { Actions, Methods } from "@/back/lib/enums";
import { AuthProp, SingleResource } from "@/back/types/global";
import { AuthProp, ConfigBackend, SingleResource } from "@/back/types/global";
import { InvoiceCompanyModel } from "@/back/types/project";
import { AppEnv } from "@/types/global";
export default function Create({
data,
@ -19,7 +18,8 @@ export default function Create({
data: SingleResource;
modelName: string;
}) {
const routeName = (usePage().props.appEnv as AppEnv).routes.name;
const routeName = (usePage().props.configBackend as ConfigBackend).routes
.name;
const { viewAny } = (usePage().props.auth as AuthProp).policies
.invoiceCompanies;
const model = data.data as InvoiceCompanyModel;

View file

@ -10,9 +10,8 @@ import Form from "@/back/Pages/InvoiceCompanies/Form";
import useTrans from "@/hooks/use-translations";
import { Actions, Methods } from "@/back/lib/enums";
import { Views } from "@/back/lib/actions";
import { AuthProp, SingleResource } from "@/back/types/global";
import { AuthProp, ConfigBackend, SingleResource } from "@/back/types/global";
import { InvoiceCompanyModel } from "@/back/types/project";
import { AppEnv } from "@/types/global";
export default function Edit({
data,
@ -21,7 +20,8 @@ export default function Edit({
data: SingleResource;
modelName: string;
}) {
const routeName = (usePage().props.appEnv as AppEnv).routes.name;
const routeName = (usePage().props.configBackend as ConfigBackend).routes
.name;
const { viewAny } = (usePage().props.auth as AuthProp).policies
.invoiceCompanies;
const model = data.data as InvoiceCompanyModel;

View file

@ -14,12 +14,11 @@ import SoftdeleteWarning from "@/back/Components/SoftdeleteWarning";
import BtnOptionnalLinkWithTooltip from "@/back/Components/BtnOptionnalLinkWithTooltip";
import { GetFormatedDate, GetTranslation } from "@/lib/utils";
import { Views } from "@/back/lib/actions";
import { AuthProp, Resource } from "@/back/types/global";
import { AuthProp, ConfigBackend, Resource } from "@/back/types/global";
import str from "@/hooks/use-string";
import useTrans from "@/hooks/use-translations";
import RenderTranslationCell from "@/back/Components/Table/RenderTranslationCell";
import { InvoicePackageModel } from "@/back/types/project";
import { AppEnv } from "@/types/global";
const getColumns = () => {
return [
@ -67,12 +66,12 @@ export default function Index({
searchFields: string;
modelName: string;
}) {
const { auth, appEnv } = usePage().props as unknown as {
const { auth, configBackend } = usePage().props as unknown as {
auth: AuthProp;
appEnv: AppEnv;
configBackend: ConfigBackend;
};
const { viewAny, viewTrash, create } = auth.policies.invoiceCompanies;
const routeName = appEnv.routes.name;
const routeName = configBackend.routes.name;
const isArchiveRoute = route().current(`${routeName}${modelName}.trash`);
const actionModels = isArchiveRoute
? [Views.RESTORATION, Views.FORCEDELETION]

View file

@ -12,12 +12,11 @@ import BtnOptionnalLinkWithTooltip from "@/back/Components/BtnOptionnalLinkWithT
import RenderTranslationCell from "@/back/Components/Table/RenderTranslationCell";
import { GetFormatedDate, GetTranslation } from "@/lib/utils";
import { Views } from "@/back/lib/actions";
import { AuthProp, SingleResource } from "@/back/types/global";
import { AuthProp, ConfigBackend, SingleResource } from "@/back/types/global";
import str from "@/hooks/use-string";
import useTrans from "@/hooks/use-translations";
import { TranslationField } from "@/back/types/i18n";
import { InvoiceCompanyModel } from "@/back/types/project";
import { AppEnv } from "@/types/global";
const getColumns = () => {
return [
@ -71,11 +70,12 @@ export default function Show({
data: SingleResource;
modelName: string;
}) {
const { auth, appEnv } = usePage().props as unknown as {
const { auth, configBackend } = usePage().props as unknown as {
auth: AuthProp;
appEnv: AppEnv;
configBackend: ConfigBackend;
};
const { viewAny } = auth.policies.invoiceCompanies;
const routeName = configBackend.routes.name;
const model = data.data as InvoiceCompanyModel;
const actionModels = [Views.EDITION, Views.DUPLICATION, Views.ARCHIVATION];
const transTitle = useTrans(
@ -98,7 +98,7 @@ export default function Show({
viewAny && (
<div className="flex justify-end items-center gap-x-1.5">
<BtnOptionnalLinkWithTooltip
link={route(`${appEnv.routes.name}${modelName}.index`)}
link={route(`${routeName}${modelName}.index`)}
content={<ArrowLeftIcon />}
tooltipContent={<p>{transCrudBackToList}</p>}
/>

View file

@ -8,9 +8,8 @@ import Form from "@/back/Pages/InvoicePackages/Form";
import BtnOptionnalLinkWithTooltip from "@/back/Components/BtnOptionnalLinkWithTooltip";
import useTrans from "@/hooks/use-translations";
import { Actions, Methods } from "@/back/lib/enums";
import { AuthProp, SingleResource } from "@/back/types/global";
import { AuthProp, ConfigBackend, SingleResource } from "@/back/types/global";
import { InvoicePackageModel } from "@/back/types/project";
import { AppEnv } from "@/types/global";
export default function Create({
data,
@ -19,7 +18,8 @@ export default function Create({
data: SingleResource;
modelName: string;
}) {
const routeName = (usePage().props.appEnv as AppEnv).routes.name;
const routeName = (usePage().props.configBackend as ConfigBackend).routes
.name;
const { viewAny } = (usePage().props.auth as AuthProp).policies
.invoicePackages;
const model = data.data as InvoicePackageModel;

View file

@ -10,9 +10,8 @@ import Form from "@/back/Pages/InvoicePackages/Form";
import useTrans from "@/hooks/use-translations";
import { Actions, Methods } from "@/back/lib/enums";
import { Views } from "@/back/lib/actions";
import { AuthProp, SingleResource } from "@/back/types/global";
import { AuthProp, ConfigBackend, SingleResource } from "@/back/types/global";
import { InvoicePackageModel } from "@/back/types/project";
import { AppEnv } from "@/types/global";
export default function Edit({
data,
@ -21,7 +20,8 @@ export default function Edit({
data: SingleResource;
modelName: string;
}) {
const routeName = (usePage().props.appEnv as AppEnv).routes.name;
const routeName = (usePage().props.configBackend as ConfigBackend).routes
.name;
const { viewAny } = (usePage().props.auth as AuthProp).policies
.invoicePackages;
const model = data.data as InvoicePackageModel;

View file

@ -21,11 +21,10 @@ import BtnOptionnalLinkWithTooltip from "@/back/Components/BtnOptionnalLinkWithT
import RenderTranslationCell from "@/back/Components/Table/RenderTranslationCell";
import { GetFormatedDate, GetTranslation } from "@/lib/utils";
import { Views } from "@/back/lib/actions";
import { AuthProp, Resource } from "@/back/types/global";
import { AuthProp, ConfigBackend, Resource } from "@/back/types/global";
import str from "@/hooks/use-string";
import useTrans from "@/hooks/use-translations";
import { InvoicePackageModel } from "@/back/types/project";
import { AppEnv } from "@/types/global";
const getColumns = () => {
return [
@ -124,12 +123,12 @@ export default function Index({
searchFields: string;
modelName: string;
}) {
const { auth, appEnv } = usePage().props as unknown as {
const { auth, configBackend } = usePage().props as unknown as {
auth: AuthProp;
appEnv: AppEnv;
configBackend: ConfigBackend;
};
const { viewAny, viewTrash, create } = auth.policies.invoicePackages;
const routeName = appEnv.routes.name;
const routeName = configBackend.routes.name;
const isArchiveRoute = route().current(`${routeName}${modelName}.trash`);
const actionModels = isArchiveRoute
? [Views.RESTORATION, Views.FORCEDELETION]

View file

@ -12,12 +12,11 @@ import BtnOptionnalLinkWithTooltip from "@/back/Components/BtnOptionnalLinkWithT
import RenderTranslationCell from "@/back/Components/Table/RenderTranslationCell";
import { GetFormatedDate, GetTranslation } from "@/lib/utils";
import { Views } from "@/back/lib/actions";
import { AuthProp, SingleResource } from "@/back/types/global";
import { AuthProp, ConfigBackend, SingleResource } from "@/back/types/global";
import str from "@/hooks/use-string";
import useTrans from "@/hooks/use-translations";
import { TranslationField } from "@/back/types/i18n";
import { InvoicePackageModel } from "@/back/types/project";
import { AppEnv } from "@/types/global";
const getColumns = () => {
return [
@ -105,11 +104,12 @@ export default function Show({
data: SingleResource;
modelName: string;
}) {
const { auth, appEnv } = usePage().props as unknown as {
const { auth, configBackend } = usePage().props as unknown as {
auth: AuthProp;
appEnv: AppEnv;
configBackend: ConfigBackend;
};
const { viewAny } = auth.policies.invoicePackages;
const routeName = configBackend.routes.name;
const model = data.data as InvoicePackageModel;
const actionModels = [Views.EDITION, Views.DUPLICATION, Views.ARCHIVATION];
const transTitle = useTrans(
@ -132,7 +132,7 @@ export default function Show({
viewAny && (
<div className="flex justify-end items-center gap-x-1.5">
<BtnOptionnalLinkWithTooltip
link={route(`${appEnv.routes.name}${modelName}.index`)}
link={route(`${routeName}${modelName}.index`)}
content={<ArrowLeftIcon />}
tooltipContent={<p>{transCrudBackToList}</p>}
/>

View file

@ -8,9 +8,8 @@ import Form from "@/back/Pages/Notices/Form";
import BtnOptionnalLinkWithTooltip from "@/back/Components/BtnOptionnalLinkWithTooltip";
import useTrans from "@/hooks/use-translations";
import { Actions, Methods } from "@/back/lib/enums";
import { AuthProp, SingleResource } from "@/back/types/global";
import { AuthProp, ConfigBackend, SingleResource } from "@/back/types/global";
import { NoticeModel } from "@/back/types/project";
import { AppEnv } from "@/types/global";
export default function Create({
data,
@ -19,7 +18,8 @@ export default function Create({
data: SingleResource;
modelName: string;
}) {
const routeName = (usePage().props.appEnv as AppEnv).routes.name;
const routeName = (usePage().props.configBackend as ConfigBackend).routes
.name;
const { viewAny } = (usePage().props.auth as AuthProp).policies.notices;
const model = data.data as NoticeModel;

View file

@ -10,9 +10,8 @@ import Form from "@/back/Pages/Notices/Form";
import useTrans from "@/hooks/use-translations";
import { Actions, Methods } from "@/back/lib/enums";
import { Views } from "@/back/lib/actions";
import { AuthProp, SingleResource } from "@/back/types/global";
import { AuthProp, ConfigBackend, SingleResource } from "@/back/types/global";
import { NoticeModel } from "@/back/types/project";
import { AppEnv } from "@/types/global";
export default function Edit({
data,
@ -21,7 +20,8 @@ export default function Edit({
data: SingleResource;
modelName: string;
}) {
const routeName = (usePage().props.appEnv as AppEnv).routes.name;
const routeName = (usePage().props.configBackend as ConfigBackend).routes
.name;
const { viewAny } = (usePage().props.auth as AuthProp).policies.notices;
const model = data.data as NoticeModel;
const actionModels = [

View file

@ -14,12 +14,12 @@ import SoftdeleteWarning from "@/back/Components/SoftdeleteWarning";
import BtnOptionnalLinkWithTooltip from "@/back/Components/BtnOptionnalLinkWithTooltip";
import { GetFormatedDate, GetTranslation } from "@/lib/utils";
import { Views } from "@/back/lib/actions";
import { AuthProp, Resource } from "@/back/types/global";
import { AuthProp, ConfigBackend, Resource } from "@/back/types/global";
import str from "@/hooks/use-string";
import useTrans from "@/hooks/use-translations";
import RenderTranslationCell from "@/back/Components/Table/RenderTranslationCell";
import { NoticeModel } from "@/back/types/project";
import { AppEnv, LaravelEnum } from "@/types/global";
import { LaravelEnum } from "@/types/global";
const getColumns = (noticeTypeEnum: LaravelEnum) => {
return [
@ -105,13 +105,14 @@ export default function Index({
searchFields: string;
modelName: string;
}) {
const { auth, appEnv, noticeTypeEnum } = usePage().props as unknown as {
const { auth, configBackend, noticeTypeEnum } = usePage()
.props as unknown as {
auth: AuthProp;
appEnv: AppEnv;
configBackend: ConfigBackend;
noticeTypeEnum: LaravelEnum;
};
const { viewAny, viewTrash, create } = auth.policies.notices;
const routeName = appEnv.routes.name;
const routeName = configBackend.routes.name;
const isArchiveRoute = route().current(`${routeName}${modelName}.trash`);
const actionModels = isArchiveRoute
? [Views.RESTORATION, Views.FORCEDELETION]

View file

@ -11,10 +11,10 @@ import ModelActions from "@/back/Components/ModelActions";
import BtnOptionnalLinkWithTooltip from "@/back/Components/BtnOptionnalLinkWithTooltip";
import { GetFormatedDate, GetTranslation } from "@/lib/utils";
import { Views } from "@/back/lib/actions";
import { AuthProp, SingleResource } from "@/back/types/global";
import { AuthProp, ConfigBackend, SingleResource } from "@/back/types/global";
import str from "@/hooks/use-string";
import useTrans from "@/hooks/use-translations";
import { AppEnv, LaravelEnum } from "@/types/global";
import { LaravelEnum } from "@/types/global";
import { TranslationField } from "@/back/types/i18n";
import RenderTranslationCell from "@/back/Components/Table/RenderTranslationCell";
import { NoticeModel } from "@/back/types/project";
@ -96,12 +96,14 @@ export default function Show({
data: SingleResource;
modelName: string;
}) {
const { auth, appEnv, noticeTypeEnum } = usePage().props as unknown as {
const { auth, configBackend, noticeTypeEnum } = usePage()
.props as unknown as {
auth: AuthProp;
appEnv: AppEnv;
configBackend: ConfigBackend;
noticeTypeEnum: LaravelEnum;
};
const { viewAny } = auth.policies.notices;
const routeName = configBackend.routes.name;
const model = data.data as NoticeModel;
const actionModels = [Views.EDITION, Views.DUPLICATION, Views.ARCHIVATION];
const transTitle = useTrans(
@ -124,7 +126,7 @@ export default function Show({
viewAny && (
<div className="flex justify-end items-center gap-x-1.5">
<BtnOptionnalLinkWithTooltip
link={route(`${appEnv.routes.name}${modelName}.index`)}
link={route(`${routeName}${modelName}.index`)}
content={<ArrowLeftIcon />}
tooltipContent={<p>{transCrudBackToList}</p>}
/>

View file

@ -8,9 +8,8 @@ import Form from "@/back/Pages/Sites/Form";
import BtnOptionnalLinkWithTooltip from "@/back/Components/BtnOptionnalLinkWithTooltip";
import useTrans from "@/hooks/use-translations";
import { Actions, Methods } from "@/back/lib/enums";
import { AuthProp, SingleResource } from "@/back/types/global";
import { AuthProp, ConfigBackend, SingleResource } from "@/back/types/global";
import { SiteModel } from "@/back/types/project";
import { AppEnv } from "@/types/global";
export default function Create({
data,
@ -19,7 +18,8 @@ export default function Create({
data: SingleResource;
modelName: string;
}) {
const routeName = (usePage().props.appEnv as AppEnv).routes.name;
const routeName = (usePage().props.configBackend as ConfigBackend).routes
.name;
const { viewAny } = (usePage().props.auth as AuthProp).policies.sites;
const model = data.data as SiteModel;

View file

@ -10,9 +10,8 @@ import Form from "@/back/Pages/Sites/Form";
import useTrans from "@/hooks/use-translations";
import { Actions, Methods } from "@/back/lib/enums";
import Views from "@/back/lib/actions";
import { AuthProp, SingleResource } from "@/back/types/global";
import { AuthProp, ConfigBackend, SingleResource } from "@/back/types/global";
import { SiteModel } from "@/back/types/project";
import { AppEnv } from "@/types/global";
export default function Edit({
data,
@ -21,7 +20,8 @@ export default function Edit({
data: SingleResource;
modelName: string;
}) {
const routeName = (usePage().props.appEnv as AppEnv).routes.name;
const routeName = (usePage().props.configBackend as ConfigBackend).routes
.name;
const { viewAny } = (usePage().props.auth as AuthProp).policies.sites;
const model = data.data as SiteModel;
const actionModels = [

View file

@ -25,12 +25,11 @@ import SoftdeleteWarning from "@/back/Components/SoftdeleteWarning";
import BtnOptionnalLinkWithTooltip from "@/back/Components/BtnOptionnalLinkWithTooltip";
import { GetFormatedDate, GetTranslation } from "@/lib/utils";
import { Views } from "@/back/lib/actions";
import { AuthProp, Resource } from "@/back/types/global";
import { AuthProp, ConfigBackend, Resource } from "@/back/types/global";
import str from "@/hooks/use-string";
import useTrans from "@/hooks/use-translations";
import { SiteModel } from "@/back/types/project";
import RenderTranslationCell from "@/back/Components/Table/RenderTranslationCell";
import { AppEnv } from "@/types/global";
const getColumns = (routeName: string, viewAnyUsers: boolean) => {
return [
@ -221,13 +220,13 @@ export default function Index({
searchFields: string;
modelName: string;
}) {
const { auth, appEnv } = usePage().props as unknown as {
const { auth, configBackend } = usePage().props as unknown as {
auth: AuthProp;
appEnv: AppEnv;
configBackend: ConfigBackend;
};
const { viewAny, viewTrash, create } = auth.policies.sites;
const { viewAny: viewAnyUsers } = auth.policies.users;
const routeName = appEnv.routes.name;
const routeName = configBackend.routes.name;
const isArchiveRoute = route().current(`${routeName}${modelName}.trash`);
const actionModels = isArchiveRoute
? [Views.RESTORATION, Views.FORCEDELETION]

View file

@ -1,12 +1,7 @@
// * Packages
import { usePage } from "@inertiajs/react";
import { route } from "ziggy-js";
import {
ArrowLeftIcon,
FolderGitIcon,
TriangleAlertIcon,
UserIcon,
} from "lucide-react";
import { ArrowLeftIcon, TriangleAlertIcon, UserIcon } from "lucide-react";
// * Components shadcn
import { Badge } from "@/components/ui/badge";
import {
@ -22,7 +17,12 @@ import BtnOptionnalLinkWithTooltip from "@/back/Components/BtnOptionnalLinkWithT
import RenderTranslationCell from "@/back/Components/Table/RenderTranslationCell";
import { GetFormatedDate, GetTranslation } from "@/lib/utils";
import { Views } from "@/back/lib/actions";
import { AuthProp, SingleResource, UserModel } from "@/back/types/global";
import {
AuthProp,
ConfigBackend,
SingleResource,
UserModel,
} from "@/back/types/global";
import str from "@/hooks/use-string";
import useTrans from "@/hooks/use-translations";
import { AppEnv } from "@/types/global";
@ -30,7 +30,8 @@ import { TranslationField } from "@/back/types/i18n";
import { GitlabProjectModel, SiteModel } from "@/back/types/project";
const getColumns = (
appEnv: AppEnv,
locale: AppEnv["locale"],
routeName: string,
viewAnyUsers: boolean,
enumUserRole: UserModel["role"][],
model: UserModel,
@ -139,7 +140,7 @@ const getColumns = (
if (viewAnyUsers && value.deleted_at === null) {
content = (
<BtnOptionnalLinkWithTooltip
link={route(`${appEnv.routes.name}users.show`, value)}
link={route(`${routeName}users.show`, value)}
content={
<>
<UserIcon />
@ -186,67 +187,7 @@ const getColumns = (
.value(),
cell: ({ value }: { value: GitlabProjectModel | null }) => {
if (value) {
const projectData = <span>{value.name[appEnv.locale]}</span>;
let content = (
<div className="flex flex-row justify-start items-center">
<Badge variant="outline">{projectData}</Badge>
{value.deleted_at !== null && (
<Tooltip>
<TooltipTrigger asChild>
<TriangleAlertIcon
size={15}
className="text-destructive ms-1"
/>
</TooltipTrigger>
<TooltipContent>
{GetTranslation("back.model_archived", {
params: {
model: str(
GetTranslation("models.classes.gitlab-projects", {
choice: 1,
}),
)
.ucFirst()
.value(),
},
choice: 1,
})}
</TooltipContent>
</Tooltip>
)}
</div>
);
if (viewAnyUsers && value.deleted_at === null) {
content = (
<BtnOptionnalLinkWithTooltip
link={route(`${appEnv.routes.name}gitlab-projects.show`, value)}
content={
<>
<FolderGitIcon />
{projectData}
</>
}
tooltipContent={
<p>
{GetTranslation("uwil-backend::back.access_model", {
params: {
model: GetTranslation(
"models.classes.gitlab-projects",
{
choice: 1,
},
),
},
})}
</p>
}
type="button"
size="default"
variant="secondary"
/>
);
}
return content;
return <span>{value.name[locale]}</span>;
}
return (
<p className="text-muted-foreground italic m-0">
@ -307,7 +248,7 @@ const getColumns = (
if (viewAnyUsers && userModel.deleted_at === null) {
content = (
<BtnOptionnalLinkWithTooltip
link={route(`${appEnv.routes.name}users.show`, userModel)}
link={route(`${routeName}users.show`, userModel)}
content={
<>
<UserIcon />
@ -403,13 +344,16 @@ export default function Show({
data: SingleResource;
modelName: string;
}) {
const { auth, appEnv, enumUserRole } = usePage().props as unknown as {
const { auth, appEnv, configBackend, enumUserRole } = usePage()
.props as unknown as {
auth: AuthProp;
appEnv: AppEnv;
configBackend: ConfigBackend;
enumUserRole: UserModel["role"][];
};
const { viewAny } = auth.policies.sites;
const { viewAny: viewAnyUsers } = auth.policies.users;
const routeName = configBackend.routes.name;
const model = data.data as SiteModel;
const actionModels = [Views.EDITION, Views.DUPLICATION, Views.ARCHIVATION];
const transTitle = useTrans(
@ -422,7 +366,13 @@ export default function Show({
},
},
);
const columns = getColumns(appEnv, viewAnyUsers, enumUserRole, auth.user);
const columns = getColumns(
appEnv.locale,
routeName,
viewAnyUsers,
enumUserRole,
auth.user,
);
// Translations.
const transCrudBackToList = useTrans("uwil-backend::back.crud_back_to_list");
@ -432,7 +382,7 @@ export default function Show({
viewAny && (
<div className="flex justify-end items-center gap-x-1.5">
<BtnOptionnalLinkWithTooltip
link={route(`${appEnv.routes.name}${modelName}.index`)}
link={route(`${routeName}${modelName}.index`)}
content={<ArrowLeftIcon />}
tooltipContent={<p>{transCrudBackToList}</p>}
/>

View file

@ -8,8 +8,12 @@ import BtnOptionnalLinkWithTooltip from "@/back/Components/BtnOptionnalLinkWithT
import Form from "@/back/Pages/Users/Form";
import useTrans from "@/hooks/use-translations";
import { Actions, Methods } from "@/back/lib/enums";
import { AuthProp, SingleResource, UserModel } from "@/back/types/global";
import { AppEnv } from "@/types/global";
import {
AuthProp,
SingleResource,
UserModel,
ConfigBackend,
} from "@/back/types/global";
export default function Create({
data,
@ -18,7 +22,8 @@ export default function Create({
data: SingleResource;
modelName: string;
}) {
const routeName = (usePage().props.appEnv as AppEnv).routes.name;
const routeName = (usePage().props.configBackend as ConfigBackend).routes
.name;
const { viewAny } = (usePage().props.auth as AuthProp).policies.users;
const model = data.data as UserModel;

View file

@ -11,8 +11,12 @@ import Form from "@/back/Pages/Users/Form";
import useTrans from "@/hooks/use-translations";
import { Actions, Methods } from "@/back/lib/enums";
import Views from "@/back/lib/actions";
import { AuthProp, SingleResource, UserModel } from "@/back/types/global";
import { AppEnv } from "@/types/global";
import {
AuthProp,
SingleResource,
UserModel,
ConfigBackend,
} from "@/back/types/global";
export default function Edit({
data,
@ -21,7 +25,8 @@ export default function Edit({
data: SingleResource;
modelName: string;
}) {
const routeName = (usePage().props.appEnv as AppEnv).routes.name;
const routeName = (usePage().props.configBackend as ConfigBackend).routes
.name;
const { viewAny } = (usePage().props.auth as AuthProp).policies.users;
const model = data.data as UserModel;
const actionModels = [

View file

@ -21,10 +21,14 @@ import BtnOptionnalLinkWithTooltip from "@/back/Components/BtnOptionnalLinkWithT
import SoftdeleteWarning from "@/back/Components/SoftdeleteWarning";
import Views from "@/back/lib/actions";
import { GetFormatedDate, GetTranslation } from "@/lib/utils";
import { AuthProp, Resource, UserModel } from "@/back/types/global";
import {
AuthProp,
ConfigBackend,
Resource,
UserModel,
} from "@/back/types/global";
import str from "@/hooks/use-string";
import useTrans from "@/hooks/use-translations";
import { AppEnv } from "@/types/global";
const getColumns = () => {
return [
@ -167,12 +171,12 @@ export default function Index({
searchFields: string;
modelName: string;
}) {
const { auth, appEnv } = usePage().props as unknown as {
const { auth, configBackend } = usePage().props as unknown as {
auth: AuthProp;
appEnv: AppEnv;
configBackend: ConfigBackend;
};
const { viewAny, viewTrash, create } = auth.policies.users;
const routeName = appEnv.routes.name;
const routeName = configBackend.routes.name;
const isArchiveRoute = route().current(`${routeName}${modelName}.trash`);
const actionModels = isArchiveRoute
? [Views.RESTORATION, Views.FORCEDELETION]

View file

@ -24,14 +24,20 @@ import BtnOptionnalLinkWithTooltip from "@/back/Components/BtnOptionnalLinkWithT
import BtnResetPassword from "@/back/Components/BtnResetPassword";
import Views from "@/back/lib/actions";
import { GetFormatedDate, GetTranslation } from "@/lib/utils";
import { AuthProp, SingleResource, UserModel } from "@/back/types/global";
import {
AuthProp,
ConfigBackend,
SingleResource,
UserModel,
} from "@/back/types/global";
import str from "@/hooks/use-string";
import useTrans from "@/hooks/use-translations";
import { AppEnv } from "@/types/global";
import { GitlabUser, SiteModel } from "@/back/types/project";
const getColumns = (
appEnv: AppEnv,
locale: AppEnv["locale"],
routeName: string,
viewAnySites: boolean,
enumUserRole: UserModel["role"][],
model: UserModel,
@ -96,7 +102,7 @@ const getColumns = (
cell: ({ value }: { value: Array<SiteModel> }) => {
if (value.length) {
const projectData = (siteModel: SiteModel) => (
<span>{siteModel.name[appEnv.locale]}</span>
<span>{siteModel.name[locale]}</span>
);
return (
<div className="flex flex-row flex-wrap justify-start items-center gap-1.5">
@ -136,7 +142,7 @@ const getColumns = (
if (viewAnySites && siteModel.deleted_at === null) {
content = (
<BtnOptionnalLinkWithTooltip
link={route(`${appEnv.routes.name}sites.show`, siteModel)}
link={route(`${routeName}sites.show`, siteModel)}
content={
<>
<GlobeIcon />
@ -262,16 +268,25 @@ export default function Show({
data: SingleResource;
modelName: string;
}) {
const { auth, appEnv, enumUserRole } = usePage().props as unknown as {
const { auth, appEnv, configBackend, enumUserRole } = usePage()
.props as unknown as {
auth: AuthProp;
appEnv: AppEnv;
configBackend: ConfigBackend;
enumUserRole: UserModel["role"][];
};
const { viewAny } = auth.policies.users;
const { viewAny: viewAnySites } = auth.policies.sites;
const routeName = configBackend.routes.name;
const model = data.data as UserModel;
const actionModels = [Views.EDITION, Views.DUPLICATION, Views.ARCHIVATION];
const columns = getColumns(appEnv, viewAnySites, enumUserRole, model);
const columns = getColumns(
appEnv.locale,
routeName,
viewAnySites,
enumUserRole,
model,
);
// Translations.
const transTitle = useTrans(
@ -291,7 +306,7 @@ export default function Show({
viewAny && (
<div className="flex justify-end items-center gap-x-1.5">
<BtnOptionnalLinkWithTooltip
link={route(`${appEnv.routes.name}${modelName}.index`)}
link={route(`${routeName}${modelName}.index`)}
content={<ArrowLeftIcon />}
tooltipContent={<p>{transCrudBackToList}</p>}
/>

View file

@ -8,6 +8,7 @@ import { Methods } from "@/back/lib/enums";
import useCrudMessages from "@/back/hooks/use-crud-messages";
import { useToast } from "@/hooks/use-toast";
import { AppEnv } from "@/types/global";
import { ConfigBackend } from "@/back/types/global";
interface CustomData {
_method?: "post" | "put";
@ -34,7 +35,10 @@ export default function useCrudSubmit<TFormData>({
data,
modelNameTrans,
}: UseCrudSubmitParams<TFormData>) {
const { locale } = usePage().props.appEnv as AppEnv;
const { appEnv, configBackend } = usePage().props as unknown as {
appEnv: AppEnv;
configBackend: ConfigBackend;
};
/** Set messages success/errors */
const messages = useCrudMessages({ method, modelNameTrans });
const { toast } = useToast();
@ -49,9 +53,12 @@ export default function useCrudSubmit<TFormData>({
// eslint-disable-next-line no-underscore-dangle, no-param-reassign
data._method = method === Methods.POST ? "post" : "put";
// eslint-disable-next-line no-param-reassign
data.locale = locale;
data.locale = appEnv.locale;
const routeUrl = route(`${modelRoute}${modelRoute}.${action}`, model?.id);
const routeUrl = route(
`${configBackend.routes.name}${modelRoute}.${action}`,
model?.id,
);
post(routeUrl, {
preserveScroll: true,
onSuccess: () => {
@ -76,7 +83,8 @@ export default function useCrudSubmit<TFormData>({
model,
post,
data,
locale,
appEnv.locale,
configBackend.routes.name,
messages.titleSuccess,
messages.descriptionSuccess,
messages.titleError,

View file

@ -4,6 +4,14 @@ import { ElementType } from "react";
// * Other
import { GitlabUser, SiteModel } from "@/back/types/project";
// Backend routes configuration.
type ConfigBackend = {
routes: {
prefix: string;
name: string;
};
};
// Policy related types.
type ModelPolicy = {
view: boolean;