Skip to content

Commit 2a3806d

Browse files
committed
feat: implement user quick actions and enhance user information display
1 parent 1ef761c commit 2a3806d

File tree

21 files changed

+571
-596
lines changed

21 files changed

+571
-596
lines changed

app/Data/Core/CoreUserData.php

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,24 @@
33
namespace App\Data\Core;
44

55
use Carbon\CarbonImmutable;
6+
use Spatie\LaravelData\Attributes\LoadRelation;
67
use Spatie\LaravelData\Data;
78

89
class CoreUserData extends Data
910
{
1011
public function __construct(
11-
public int $id,
12-
public string $uuid,
12+
public int $id,
13+
public string $uuid,
1314
public ?CarbonImmutable $last_seen,
14-
public ?string $last_server,
15-
public ?string $last_name,
15+
public ?string $last_server,
16+
public ?string $last_name,
1617
public ?CarbonImmutable $created_at,
1718
public ?CarbonImmutable $updated_at,
18-
) {}
19+
20+
/** @var array<CoreUserNameHistoryData> */
21+
#[LoadRelation]
22+
public array $name_histories,
23+
)
24+
{
25+
}
1926
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?php
2+
3+
namespace App\Data\Core;
4+
5+
use Carbon\CarbonImmutable;
6+
use Spatie\LaravelData\Data;
7+
8+
class CoreUserNameHistoryData extends Data
9+
{
10+
public function __construct(
11+
public int $id,
12+
public string $name,
13+
public ?CarbonImmutable $created_at,
14+
)
15+
{
16+
}
17+
}

app/Http/Controllers/Core/CoreUserController.php

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ public function index(Request $request)
1919
$users = CoreUser::where("last_name", "LIKE", "%$query%")
2020
->orWhere("uuid", $query)->paginate(100)->withQueryString();
2121

22-
return Inertia::render('panel/core/users/index', [
22+
return Inertia::render('panel/core/users/index/page', [
2323
'users' => CoreUserData::collect($users),
2424
'query' => $query,
2525
]);
@@ -28,5 +28,10 @@ public function index(Request $request)
2828
/**
2929
* Display the specified resource.
3030
*/
31-
public function show(CoreUser $user) {}
31+
public function show(CoreUser $user)
32+
{
33+
return Inertia::render('panel/core/users/show/page', [
34+
'user' => CoreUserData::from($user),
35+
]);
36+
}
3237
}

app/Models/Core/CoreUser.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,11 @@ class CoreUser extends Model
1717
'last_seen' => 'datetime',
1818
];
1919

20+
public function nameHistories()
21+
{
22+
return $this->hasMany(CoreUserNameHistory::class);
23+
}
24+
2025
public function getRouteKeyName(): string
2126
{
2227
return 'uuid';
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?php
2+
3+
namespace App\Models\Core;
4+
5+
use Illuminate\Database\Eloquent\Model;
6+
7+
class CoreUserNameHistory extends Model
8+
{
9+
protected $fillable = [
10+
"name",
11+
"user_id"
12+
];
13+
14+
public function user()
15+
{
16+
return $this->belongsTo(CoreUser::class);
17+
}
18+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?php
2+
3+
use Illuminate\Database\Migrations\Migration;
4+
use Illuminate\Database\Schema\Blueprint;
5+
use Illuminate\Support\Facades\Schema;
6+
7+
return new class extends Migration {
8+
/**
9+
* Run the migrations.
10+
*/
11+
public function up(): void
12+
{
13+
Schema::create('core_user_name_histories', function (Blueprint $table) {
14+
$table->id();
15+
$table->char('name', 16);
16+
$table->foreignId('core_user_id')->constrained('core_users')->cascadeOnDelete()->cascadeOnUpdate();
17+
$table->datetimes();
18+
});
19+
}
20+
21+
/**
22+
* Reverse the migrations.
23+
*/
24+
public function down(): void
25+
{
26+
Schema::dropIfExists('core_user_name_histories');
27+
}
28+
};
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import {IconType} from "react-icons/lib";
2+
3+
export function IconText({icon: Icon, text, children}: {
4+
icon: IconType;
5+
text?: string;
6+
children?: any
7+
}) {
8+
return <span className={"inline-flex items-center flex-row gap-1"}>
9+
{Icon && <Icon/>}
10+
{text && <span>{text}</span>}
11+
{children}
12+
</span>
13+
}
Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,35 @@
11
"use client";
22

3-
import { useTheme } from "next-themes";
4-
import { Toaster as Sonner } from "sonner";
3+
import {useTheme} from "next-themes";
4+
import {Toaster as Sonner} from "sonner";
55

66
type ToasterProps = React.ComponentProps<typeof Sonner>;
77

8-
const Toaster = ({ ...props }: ToasterProps) => {
9-
const { theme = "system" } = useTheme();
8+
const Toaster = ({...props}: ToasterProps) => {
9+
const {theme = "system"} = useTheme();
1010

1111
return (
1212
<Sonner
13-
richColors
1413
theme={theme as ToasterProps["theme"]}
1514
className="toaster group"
1615
toastOptions={{
1716
classNames: {
18-
toast: "group toast group-[.toaster]:bg-background group-[.toaster]:text-foreground group-[.toaster]:border-border group-[.toaster]:shadow-lg",
17+
toast: "group toast border-t-2 rounded-none rounded-b",
1918
description: "group-[.toast]:text-muted-foreground",
2019
actionButton:
2120
"group-[.toast]:bg-primary group-[.toast]:text-primary-foreground",
2221
cancelButton:
2322
"group-[.toast]:bg-muted group-[.toast]:text-muted-foreground",
23+
success: "border-t-success",
24+
error: "border-t-danger",
25+
loading: "border-t-primary",
26+
info: "border-t-info",
27+
warning: "border-t-warning",
2428
},
2529
}}
2630
{...props}
2731
/>
2832
);
2933
};
3034

31-
export { Toaster };
35+
export {Toaster};
Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,34 @@
1-
import { AppSidebar } from "@/components/navigation/sidebar/app-sidebar";
1+
import {AppSidebar} from "@/components/navigation/sidebar/app-sidebar";
22
import {
33
Breadcrumb,
44
BreadcrumbItem,
55
BreadcrumbLink,
66
BreadcrumbList,
77
BreadcrumbSeparator,
88
} from "@/components/ui/breadcrumb";
9-
import { Separator } from "@/components/ui/separator";
10-
import {
11-
SidebarInset,
12-
SidebarProvider,
13-
SidebarTrigger,
14-
} from "@/components/ui/sidebar";
15-
import { PageProps } from "@/types/helper-types";
16-
import { usePage } from "@inertiajs/react";
17-
import { ThemeProvider } from "next-themes";
18-
import { PropsWithChildren } from "react";
9+
import {Separator} from "@/components/ui/separator";
10+
import {SidebarInset, SidebarProvider, SidebarTrigger,} from "@/components/ui/sidebar";
11+
import {PageProps} from "@/types/helper-types";
12+
import {usePage} from "@inertiajs/react";
13+
import {ThemeProvider} from "next-themes";
14+
import {PropsWithChildren} from "react";
15+
import {Toaster} from "@/components/ui/sonner";
1916

2017
export default function AuthenticatedLayout({
21-
children,
22-
}: PropsWithChildren<{}>) {
18+
children,
19+
}: PropsWithChildren<{}>) {
2320
const page = usePage<PageProps>().props;
2421
const user = page.auth.user;
2522
const breadcrumbs = page.breadcrumbs;
2623

2724
return (
2825
<ThemeProvider defaultTheme="dark" attribute={"class"}>
2926
<SidebarProvider>
30-
<AppSidebar user={user} />
27+
<AppSidebar user={user}/>
3128
<SidebarInset>
3229
<header className="flex h-12 shrink-0 items-center gap-2">
3330
<div className="flex items-center gap-2 px-4">
34-
<SidebarTrigger className="-ml-1" />
31+
<SidebarTrigger className="-ml-1"/>
3532
<Separator
3633
orientation="vertical"
3734
className="mr-2 h-4"
@@ -52,19 +49,21 @@ export default function AuthenticatedLayout({
5249
</BreadcrumbItem>
5350

5451
{index < breadcrumbs.length - 1 && (
55-
<BreadcrumbSeparator />
52+
<BreadcrumbSeparator/>
5653
)}
5754
</div>
5855
))}
5956
</BreadcrumbList>
6057
</Breadcrumb>
6158
</div>
6259
</header>
63-
<main className="p-4 lg:p-6 flex flex-col gap-6">
60+
<main className="p-4 lg:p-6 flex flex-col gap-6 relative">
6461
{children}
6562
</main>
6663
</SidebarInset>
6764
</SidebarProvider>
65+
66+
<Toaster/>
6867
</ThemeProvider>
6968
);
7069
}

resources/js/lib/date-utils.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,19 @@
11
/* eslint-disable @typescript-eslint/no-unsafe-argument */
2-
import { format } from "date-fns";
3-
import { de } from "date-fns/locale";
2+
import {format} from "date-fns";
3+
import {de} from "date-fns/locale";
44

5-
export function formatDate(date?: Date | null) {
5+
export function formatDate(date?: Date | string | null) {
66
if (date === null || date === undefined) {
77
return "/";
88
}
99

10-
return format(date, "EEEE, dd. MMMM yyyy", { locale: de });
10+
return format(date, "EEEE, dd. MMMM yyyy", {locale: de});
1111
}
1212

13-
export function formatDateTime(date?: Date | null) {
13+
export function formatDateTime(date?: Date | string | null) {
1414
if (date === null || date === undefined) {
1515
return "/";
1616
}
1717

18-
return format(date, "EEEE, dd. MMMM yyyy, HH:mm", { locale: de });
18+
return format(date, "EEEE, dd. MMMM yyyy, HH:mm", {locale: de});
1919
}

0 commit comments

Comments
 (0)