Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
ea9be0a
refactor: adopt DDD with rich domain models, migrate to MikroORM, and…
KerollosMelad Jul 2, 2025
2be96b9
refactor: update sign-in and sign-up forms to use fetch API for authe…
KerollosMelad Jul 2, 2025
02752e9
refactor: migrate todo actions to API routes for improved consistency…
KerollosMelad Jul 2, 2025
3478ec2
refactor: enhance MikroORM configuration for serverless compatibility
KerollosMelad Jul 2, 2025
442237d
refactor: update entity relationships to use object notation for Mikr…
KerollosMelad Jul 2, 2025
a27eb05
refactor: update MikroORM reflection dependency and improve entity ty…
KerollosMelad Jul 2, 2025
40171a7
refactor: streamline entity imports and enhance MikroORM configuration
KerollosMelad Jul 2, 2025
b0784e3
refactor: update MikroORM configuration for direct entity imports and…
KerollosMelad Jul 2, 2025
19143fb
refactor: simplify entity relationships by removing lazy loading
KerollosMelad Jul 2, 2025
a9e4421
chore: enhance MikroORM configuration and update .gitignore
KerollosMelad Jul 2, 2025
bb5452c
refactor: improve MikroORM configuration and documentation for server…
KerollosMelad Jul 2, 2025
b64331f
chore: update package.json scripts and enhance MikroORM deployment do…
KerollosMelad Jul 2, 2025
d431037
refactor: enhance entity relationships with explicit foreign key refe…
KerollosMelad Jul 2, 2025
17f6f88
chore: enhance MikroORM configuration with improved logging and cache…
KerollosMelad Jul 2, 2025
df99097
chore: enhance MikroORM configuration with cache control and logging …
KerollosMelad Jul 2, 2025
80a0bab
refactor: enhance MikroORM initialization and error handling in instr…
KerollosMelad Jul 2, 2025
326c01e
refactor: simplify MikroORM configuration for Vercel deployment
KerollosMelad Jul 2, 2025
89e9f24
refactor: enhance entity management and registration in MikroORM
KerollosMelad Jul 2, 2025
d8f334e
refactor: update entity property visibility for consistency
KerollosMelad Jul 2, 2025
6fa295f
refactor: reorganize entity imports in MikroORM configuration
KerollosMelad Jul 2, 2025
22cdb7f
refactor: update entity imports and relationships for consistency
KerollosMelad Jul 2, 2025
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
14 changes: 9 additions & 5 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
SENTRY_DSN=
NEXT_PUBLIC_SENTRY_DSN=
SENTRY_AUTH_TOKEN=
CODECOV_TOKEN=
DATABASE_HOST=
DATABASE_PORT=
DATABASE_NAME=
DATABASE_USER=
DATABASE_PASSWORD=
DATABASE_URL=
DATABASE_AUTH_TOKEN=
NEXT_PUBLIC_SUPABASE_URL=
NEXT_PUBLIC_SUPABASE_ANON_KEY=


20 changes: 10 additions & 10 deletions .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,18 @@
},
{
"mode": "full",
"type": "use-cases",
"pattern": ["src/application/use-cases/**/*"]
"type": "application-services",
"pattern": ["src/application/modules/**/*"]
},
{
"mode": "full",
"type": "service-interfaces",
"pattern": ["src/application/services/**/*"]
"pattern": ["src/application/modules/**/interfaces/**/*", "src/application/services/**/*"]
},
{
"mode": "full",
"type": "repository-interfaces",
"pattern": ["src/application/repositories/**/*"]
"pattern": ["src/application/modules/**/interfaces/**/*"]
},
{
"mode": "full",
Expand Down Expand Up @@ -56,24 +56,24 @@
"rules": [
{
"from": "web",
"allow": ["web", "entities", "di"]
"allow": ["web", "entities", "di", "infrastructure", "application-services", "service-interfaces"]
},
{
"from": "controllers",
"allow": [
"entities",
"service-interfaces",
"repository-interfaces",
"use-cases"
"application-services"
]
},
{
"from": "infrastructure",
"allow": ["service-interfaces", "repository-interfaces", "entities"]
"allow": ["service-interfaces", "repository-interfaces", "entities", "infrastructure", "application-services"]
},
{
"from": "use-cases",
"allow": ["entities", "service-interfaces", "repository-interfaces"]
"from": "application-services",
"allow": ["entities", "service-interfaces", "repository-interfaces", "infrastructure", "application-services"]
},
{
"from": "service-interfaces",
Expand All @@ -94,7 +94,7 @@
"controllers",
"service-interfaces",
"repository-interfaces",
"use-cases",
"application-services",
"infrastructure"
]
}
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,6 @@ sqlite.db

# Environment variables
.env

# MikroORM metadata cache
/temp/
142 changes: 0 additions & 142 deletions app/(auth)/actions.ts

This file was deleted.

42 changes: 33 additions & 9 deletions app/(auth)/sign-in/page.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
'use client';

import Link from 'next/link';
import { useState } from 'react';
import { Loader } from 'lucide-react';
import { useRouter } from 'next/navigation';

import Link from 'next/link';
import { Button } from '../../_components/ui/button';
import {
Card,
Expand All @@ -15,32 +16,55 @@ import {
import { Input } from '../../_components/ui/input';
import { Label } from '../../_components/ui/label';
import { Separator } from '../../_components/ui/separator';
import { signIn } from '../actions';

export default function SignIn() {
const [error, setError] = useState<string>();
const [loading, setLoading] = useState(false);
const router = useRouter();

const handleSubmit = async (event: React.FormEvent<HTMLFormElement>) => {
event.preventDefault();
if (loading) return;

const formData = new FormData(event.currentTarget);
const username = formData.get('username')?.toString();
const password = formData.get('password')?.toString();

if (!username || !password) {
setError('Username and password are required');
return;
}

setLoading(true);
const res = await signIn(formData);
if (res && res.error) {
setError(res.error);
setError(undefined);

try {
const response = await fetch('/api/auth/sign-in', {
method: 'POST',
body: formData,
});

const result = await response.json();

if (response.ok && result.success) {
router.push('/');
router.refresh();
} else {
setError(result.error || 'Invalid credentials');
}
} catch (error) {
setError('Network error. Please try again.');
} finally {
setLoading(false);
}
setLoading(false);
};

return (
<Card className="w-full max-w-lg">
<CardHeader>
<CardTitle>Sign in</CardTitle>
<CardDescription>
Enter your email below to login to your account
Enter your username and password to access your account
</CardDescription>
</CardHeader>
<Separator />
Expand All @@ -63,13 +87,13 @@ export default function SignIn() {
<Input id="password" type="password" name="password" required />
</div>
<Button type="submit" disabled={loading} className="w-full">
{loading ? <Loader className="animate-spin" /> : 'Login'}
{loading ? <Loader className="animate-spin" /> : 'Sign in'}
</Button>
</div>
<div className="mt-4 text-center text-sm">
Don&apos;t have an account?{' '}
<Link href="/sign-up" className="underline">
Sign up
Create an account
</Link>
</div>
</form>
Expand Down
35 changes: 28 additions & 7 deletions app/(auth)/sign-up/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import Link from 'next/link';
import { useState } from 'react';
import { Loader } from 'lucide-react';
import { useRouter } from 'next/navigation';

import { Button } from '../../_components/ui/button';
import {
Expand All @@ -15,32 +16,52 @@ import {
import { Input } from '../../_components/ui/input';
import { Label } from '../../_components/ui/label';
import { Separator } from '../../_components/ui/separator';
import { signUp } from '../actions';

export default function SignUp() {
const [error, setError] = useState<string>();
const [loading, setLoading] = useState(false);
const router = useRouter();

const handleSubmit = async (event: React.FormEvent<HTMLFormElement>) => {
event.preventDefault();
if (loading) return;

const formData = new FormData(event.currentTarget);
const password = formData.get('password')?.toString();
const confirmPassword = formData.get('confirm_password')?.toString();

const password = formData.get('password')!.toString();
const confirmPassword = formData.get('confirm_password')!.toString();
if (!password || !confirmPassword) {
setError('All fields are required');
return;
}

if (password !== confirmPassword) {
setError('Passwords must match');
return;
}

setLoading(true);
const res = await signUp(formData);
if (res && res.error) {
setError(res.error);
setError(undefined);

try {
const response = await fetch('/api/auth/sign-up', {
method: 'POST',
body: formData,
});

const result = await response.json();

if (response.ok && result.success) {
router.push('/');
router.refresh();
} else {
setError(result.error || 'An unexpected error occurred');
}
} catch (error) {
setError('Network error. Please try again.');
} finally {
setLoading(false);
}
setLoading(false);
};

return (
Expand Down
Loading