Skip to content

Commit

Permalink
(backend): add user creation logic
Browse files Browse the repository at this point in the history
  • Loading branch information
camwhit-e committed Oct 24, 2024
1 parent 8e3510a commit f580850
Show file tree
Hide file tree
Showing 5 changed files with 164 additions and 1 deletion.
27 changes: 27 additions & 0 deletions app/Http/Controllers/UsersController.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,31 @@ public function index(Request $request): Response
'users' => User::all(),
]);
}

/**
* Display the form for creating a new user.
*/
public function new(Request $request): Response
{
return Inertia::render('Users/New');
}

/**
* Store a new user request.
*/
public function store(Request $request): Response
{
$validated = $request->validate([
'name' => ['required', 'max:50', 'unique:users,name'],
'email' => ['required', 'max:50', 'email', 'unique:users,email'],
'password' => ['required', 'min:8'],
'superuser' => ['required'],
]);

$validated['superuser'] = $validated['superuser'] === 'on' ? true : false;

User::create($validated);

return Inertia::render('Users/Index');
}
}
2 changes: 1 addition & 1 deletion resources/js/Components/PrimaryButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export default function PrimaryButton({
<button
{...props}
className={
`inline-flex items-center rounded-md border border-transparent bg-gray-800 px-4 py-2 text-xs font-semibold uppercase tracking-widest text-white transition duration-150 ease-in-out hover:bg-gray-700 focus:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-green-500 focus:ring-offset-2 active:bg-gray-900 dark:bg-gray-200 dark:text-gray-800 dark:hover:bg-white dark:focus:bg-white dark:focus:ring-offset-gray-800 dark:active:bg-gray-300 ${
`inline-flex items-center rounded-md border border-transparent bg-zinc-800 px-4 py-2 text-xs font-semibold uppercase tracking-widest text-gray-200 transition duration-150 ease-in-out hover:bg-gray-700 focus:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-green-500 focus:ring-offset-2 dark:focus:ring-offset-gray-800 ${
disabled && 'opacity-25'
} ` + className
}
Expand Down
7 changes: 7 additions & 0 deletions resources/js/Pages/Users/Index.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
import PrimaryButton from '@/Components/PrimaryButton';
import { Body, Head } from '@/Components/Table';
import Authenticated from '@/Layouts/AuthenticatedLayout';
import { PageProps, User } from '@/types';
import { Link } from '@inertiajs/react';
import Avatar from 'boring-avatars';

export default function Index({ users }: PageProps<{ users: User[] }>) {
return (
<Authenticated title={'All Users'}>
<div className={'mb-4 text-right'}>
<Link href={'/users/new'}>
<PrimaryButton>New User</PrimaryButton>
</Link>
</div>
<table className="w-full text-left text-sm text-gray-400">
<Head columns={['Name', 'Position', 'Status', 'Action']} />
<Body>
Expand Down
127 changes: 127 additions & 0 deletions resources/js/Pages/Users/New.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
import Card from '@/Components/Card';
import PrimaryButton from '@/Components/PrimaryButton';
import Authenticated from '@/Layouts/AuthenticatedLayout';
import { router } from '@inertiajs/react';
import Avatar from 'boring-avatars';
import { useState } from 'react';

export default function New() {
const [values, setValues] = useState({
email: '',
name: '',
password: '',
superuser: false,
});

function handleChange(e: {
target: { id: string; value: string | boolean };
}) {
const key = e.target.id;
const value = e.target.value;
setValues((values) => ({
...values,
[key]: value,
}));
}

function handleSubmit(e: { preventDefault: () => void }) {
e.preventDefault();
router.post('/users/new', values);
}

return (
<Authenticated title={'All Users'}>
<Card
header={'Create new user'}
description={'Add a new user to the management interface.'}
>
<div className={'grid gap-6 lg:grid-cols-3'}>
<div className={'grid items-center justify-center'}>
<div>
<Avatar
name={'0'}
className={'h-24'}
variant={'beam'}
/>
</div>
</div>
<form
className="lg:col-span-2"
autoComplete={'off'}
onSubmit={handleSubmit}
>
<div className="group relative z-0 mb-5 w-full">
<input
type="email"
name="email"
id="email"
onChange={handleChange}
className="peer block w-full appearance-none border-0 border-b-2 border-gray-300 bg-transparent px-0 py-2.5 text-sm text-gray-900 focus:border-green-600 focus:outline-none focus:ring-0 dark:border-gray-600 dark:text-white dark:focus:border-green-500"
placeholder=" "
required
/>
<label className="absolute top-3 -z-10 origin-[0] -translate-y-6 scale-75 transform text-sm text-gray-500 duration-300 peer-placeholder-shown:translate-y-0 peer-placeholder-shown:scale-100 peer-focus:start-0 peer-focus:-translate-y-6 peer-focus:scale-75 peer-focus:font-medium peer-focus:text-green-600 dark:text-gray-400 peer-focus:dark:text-green-500">
Email address
</label>
</div>
<div className="group relative z-0 mb-5 w-full">
<input
type="password"
name="password"
id="password"
onChange={handleChange}
className="peer block w-full appearance-none border-0 border-b-2 border-gray-300 bg-transparent px-0 py-2.5 text-sm text-gray-900 focus:border-green-600 focus:outline-none focus:ring-0 dark:border-gray-600 dark:text-white dark:focus:border-green-500"
placeholder=" "
required
/>
<label
htmlFor="password"
className="absolute top-3 -z-10 origin-[0] -translate-y-6 scale-75 transform text-sm text-gray-500 duration-300 peer-placeholder-shown:translate-y-0 peer-placeholder-shown:scale-100 peer-focus:start-0 peer-focus:-translate-y-6 peer-focus:scale-75 peer-focus:font-medium peer-focus:text-green-600 rtl:peer-focus:translate-x-1/4 dark:text-gray-400 peer-focus:dark:text-green-500"
>
Password
</label>
</div>
<div className="grid md:grid-cols-2 md:gap-6">
<div className="group relative z-0 mb-5 w-full">
<input
type="text"
name="name"
id="name"
className="peer block w-full appearance-none border-0 border-b-2 border-gray-300 bg-transparent px-0 py-2.5 text-sm text-gray-900 focus:border-green-600 focus:outline-none focus:ring-0 dark:border-gray-600 dark:text-white dark:focus:border-green-500"
placeholder=" "
onChange={handleChange}
required
/>
<label
htmlFor="name"
className="absolute top-3 -z-10 origin-[0] -translate-y-6 scale-75 transform text-sm text-gray-500 duration-300 peer-placeholder-shown:translate-y-0 peer-placeholder-shown:scale-100 peer-focus:start-0 peer-focus:-translate-y-6 peer-focus:scale-75 peer-focus:font-medium peer-focus:text-green-600 rtl:peer-focus:translate-x-1/4 dark:text-gray-400 peer-focus:dark:text-green-500"
>
name
</label>
</div>
<div className="mb-4 flex items-center">
<input
id="superuser"
type="checkbox"
onChange={handleChange}
className="h-4 w-4 rounded border-gray-300 bg-gray-100 text-green-600 focus:ring-2 focus:ring-green-500 dark:border-gray-600 dark:bg-gray-700 dark:ring-offset-gray-800 dark:focus:ring-green-600 dark:focus:ring-offset-gray-800"
/>
<label
htmlFor="superuser"
className="ms-2 text-sm font-medium text-gray-900 dark:text-gray-300"
>
Grant this account Superuser permissions
</label>
</div>
</div>
<div className={'text-right'}>
<PrimaryButton type={'submit'}>
Submit
</PrimaryButton>
</div>
</form>
</div>
</Card>
</Authenticated>
);
}
2 changes: 2 additions & 0 deletions routes/web.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
Route::middleware('auth')->group(function () {
Route::prefix('/users')->group(function () {
Route::get('/', [UsersController::class, 'index'])->name('users.index');
Route::get('/new', [UsersController::class, 'new'])->name('users.new');
Route::post('/new', [UsersController::class, 'store'])->name('users.store');
});

Route::prefix('/profile')->group(function () {
Expand Down

0 comments on commit f580850

Please sign in to comment.