Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Database configuration

PG_HOST:
PG_USERNAME:
PG_PASSWORD:
RAILS_MAX_THREADS: 5
PG_PORT: 5432
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
/.bundle

# Ignore all environment files.
/.env*
/.env

# Ignore all logfiles and tempfiles.
/log/*
Expand Down
2 changes: 2 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -76,3 +76,5 @@ gem "dotenv-rails", "~> 3.1", groups: [ :development, :test ]
gem "inertia_rails", "~> 3.11"

gem "vite_rails", "~> 3.0"

gem "devise", "~> 4.9"
14 changes: 14 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ GEM
public_suffix (>= 2.0.2, < 7.0)
ast (2.4.3)
base64 (0.3.0)
bcrypt (3.1.20)
bcrypt_pbkdf (1.1.1)
bigdecimal (3.3.1)
bindex (0.8.1)
Expand Down Expand Up @@ -110,6 +111,12 @@ GEM
debug (1.11.0)
irb (~> 1.10)
reline (>= 0.3.8)
devise (4.9.4)
bcrypt (~> 3.0)
orm_adapter (~> 0.1)
railties (>= 4.1.0)
responders
warden (~> 1.2.3)
diff-lcs (1.6.2)
dotenv (3.1.8)
dotenv-rails (3.1.8)
Expand Down Expand Up @@ -216,6 +223,7 @@ GEM
racc (~> 1.4)
nokogiri (1.18.10-x86_64-linux-musl)
racc (~> 1.4)
orm_adapter (0.5.0)
ostruct (0.6.3)
parallel (1.27.0)
parser (3.3.10.0)
Expand Down Expand Up @@ -291,6 +299,9 @@ GEM
regexp_parser (2.11.3)
reline (0.6.2)
io-console (~> 0.5)
responders (3.2.0)
actionpack (>= 7.0)
railties (>= 7.0)
rexml (3.4.4)
rspec-core (3.13.6)
rspec-support (~> 3.13.0)
Expand Down Expand Up @@ -400,6 +411,8 @@ GEM
mutex_m
rack-proxy (~> 0.6, >= 0.6.1)
zeitwerk (~> 2.2)
warden (1.2.9)
rack (>= 2.0.9)
web-console (4.2.1)
actionview (>= 6.0.0)
activemodel (>= 6.0.0)
Expand Down Expand Up @@ -431,6 +444,7 @@ DEPENDENCIES
capybara
database_cleaner-active_record
debug
devise (~> 4.9)
dotenv-rails (~> 3.1)
factory_bot_rails
image_processing (~> 1.2)
Expand Down
6 changes: 6 additions & 0 deletions app/assets/stylesheets/application.css
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,9 @@
*
* Consider organizing styles into separate files for maintainability.
*/

* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
14 changes: 10 additions & 4 deletions app/controllers/application_controller.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
class ApplicationController < ActionController::Base
# Only allow modern browsers supporting webp images, web push, badges, import maps, CSS nesting, and CSS :has.
allow_browser versions: :modern
before_action :authenticate_user!

# Changes to the importmap will invalidate the etag for HTML responses
stale_when_importmap_changes
inertia_share do
{
flash: {
notice: flash.notice,
alert: flash.alert
},
current_user: current_user&.slice(:id, :email)
}
end
end
7 changes: 7 additions & 0 deletions app/controllers/home_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
class HomeController < ApplicationController
def index
render inertia: "Home", props: {
welcomeMessage: "Welcome to the Home Page!"
}
end
end
9 changes: 0 additions & 9 deletions app/controllers/inertia_example_controller.rb

This file was deleted.

5 changes: 5 additions & 0 deletions app/controllers/users/registrations_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class Users::RegistrationsController < Devise::RegistrationsController
def new
render inertia: "Auth/Register"
end
end
27 changes: 27 additions & 0 deletions app/controllers/users/sessions_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# frozen_string_literal: true

class Users::SessionsController < Devise::SessionsController
# before_action :configure_sign_in_params, only: [:create]

# GET /resource/sign_in
def new
render inertia: "Auth/Login"
end

# POST /resource/sign_in
# def create
# super
# end

# DELETE /resource/sign_out
# def destroy
# super
# end

# protected

# If you have extra params to permit, append them to the sanitizer.
# def configure_sign_in_params
# devise_parameter_sanitizer.permit(:sign_in, keys: [:attribute])
# end
end
14 changes: 14 additions & 0 deletions app/frontend/entrypoints/application.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/* Frontend Application Styles */
@import "tailwindcss";

* {
margin: 0;
padding: 0;
box-sizing: border-box;
}

body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
line-height: 1.6;
}

9 changes: 7 additions & 2 deletions app/frontend/entrypoints/inertia.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// frontend/entrypoints/inertia.js
import './application.css'
import { createInertiaApp } from '@inertiajs/react'
import { createElement } from 'react'
import { createRoot } from 'react-dom/client'
Expand All @@ -7,10 +8,14 @@ import Layout from '../components/Layout'
createInertiaApp({
resolve: (name) => {
const pages = import.meta.glob('../pages/**/*.jsx', { eager: true })
let page = pages[`../pages/${name}.jsx`]
const page = pages[`../pages/${name}.jsx`]

if (!page) {
throw new Error(`Page not found: ${name}`)
}

// Se a página NÃO tiver um layout próprio, aplica o Layout padrão
page.default.layout = page.default.layout || (() => createElement(Layout, { children: page }))
page.default.layout = page.default.layout || ((page) => createElement(Layout, null, page))

return page
},
Expand Down
111 changes: 111 additions & 0 deletions app/frontend/pages/Auth/Login.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
import { useForm, Link } from '@inertiajs/react'

Check failure on line 1 in app/frontend/pages/Auth/Login.jsx

View workflow job for this annotation

GitHub Actions / pnpm lint

'Link' is defined but never used

export default function Login() {
const { data, setData, post, processing, errors } = useForm({
user: { email: '',
password: '',
remember_me: false}
})

const handleSubmit = (e) => {
e.preventDefault()
// POST para a rota do Devise
post('/users/sign_in', {
data: {user: {data}},
onError: (errors) => {
console.log('Erro no login:', errors)

Check failure on line 16 in app/frontend/pages/Auth/Login.jsx

View workflow job for this annotation

GitHub Actions / pnpm lint

'console' is not defined
}
})
}

return (
<div className="min-h-screen grid grid-cols-2 bg-gray-100">
<div className='col-span-1 bg-[#F28D1C]'>

</div>
<div className="col-span-1 flex min-w-full flex-col justify-center items-center bg-white p-8 rounded-lg shadow-md w-full max-w-md">
<h1 className="items-center text-[#F28D1C] text-2xl font-semibold">Login</h1>

<form onSubmit={handleSubmit}>
{/* Campo de Email */}
<div className="mb-4">
<label htmlFor="email" className="block text-gray-700 font-medium mb-2">
Email
</label>
<input
id="email"
type="email"
value={data.user.email}
onChange={(e) => setData('user.email', e.target.value)}
className="w-full px-3 py-2 border border-gray-300 rounded focus:outline-none focus:ring-2 focus:ring-blue-500"
autoFocus
/>
{errors.user?.email && (
<div className="text-red-500 text-sm mt-1">{errors.user.email}</div>
)}
</div>

{/* Campo de Senha */}
<div className="mb-4">
<label htmlFor="password" className="block text-gray-700 font-medium mb-2">
Senha
</label>
<input
id="password"
type="password"
value={data.user.password}
onChange={(e) => setData('user.password', e.target.value)}
className="w-full px-3 py-2 border border-gray-300 rounded focus:outline-none focus:ring-2 focus:ring-blue-500"
/>
{errors.user?.password && (
<div className="text-red-500 text-sm mt-1">{errors.user.password}</div>
)}
</div>

{/* Checkbox Lembrar-me */}
<div className="mb-4 flex items-center">
<input
id="remember_me"
type="checkbox"
checked={data.user.remember_me}
onChange={(e) => setData('user.remember_me', e.target.checked)}
className="mr-2"
/>
<label htmlFor="remember_me" className="text-gray-700">
Lembrar-me
</label>
</div>

{/* Erro geral (se houver) */}
{errors.error && (
<div className="mb-4 p-3 bg-red-100 text-red-700 rounded">
{errors.error}
</div>
)}

{/* Botão de Submit */}
<button
type="submit"
disabled={processing}
className="w-full bg-blue-500 text-white py-2 px-4 rounded hover:bg-blue-600 disabled:bg-gray-400 disabled:cursor-not-allowed"
>
{processing ? 'Entrando...' : 'Entrar'}
</button>

{/* Links auxiliares */}
<div className="mt-4 text-center">
<Link href="/users/sign_up" className="text-blue-500 hover:underline">
Não tem conta? Cadastre-se
</Link>
</div>

<div className="mt-2 text-center">
<Link href="/users/password/new" className="text-blue-500 hover:underline text-sm">
Esqueceu a senha?
</Link>
</div>
</form>
</div>
</div>
)
}
Loading
Loading