Skip to content
Merged
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
2,145 changes: 2,145 additions & 0 deletions app/Icons/Android.php

Large diffs are not rendered by default.

2,145 changes: 2,145 additions & 0 deletions app/Icons/AndroidOutlined.php

Large diffs are not rendered by default.

7,854 changes: 7,854 additions & 0 deletions app/Icons/Ios.php

Large diffs are not rendered by default.

21 changes: 21 additions & 0 deletions app/NativeComponents/Eventos.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php

declare(strict_types=1);

namespace App\NativeComponents;

use Illuminate\View\View;
use Native\Mobile\Edge\NativeComponent;

class Eventos extends NativeComponent
{
public function navTitle(): string
{
return 'Eventos';
}

public function render(): View
{
return view('native.eventos');
}
}
98 changes: 84 additions & 14 deletions app/NativeComponents/Home.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,34 +4,104 @@

namespace App\NativeComponents;

use Illuminate\Support\Facades\Http;
use Illuminate\View\View;
use Native\Mobile\Edge\NativeComponent;
use Native\Mobile\Facades\Browser;

class Home extends NativeComponent
{
public string $status = 'loading';
/**
* Mock — a API real de estatísticas da comunidade ainda não existe
* (ver docs/plans/2026-09-22-api-mobile-jwt.md no heartdevs.com).
*
* @var array{membros: string, online: string, mensagens: string}
*/
public array $stats = [
'membros' => '9.2k+',
'online' => '184',
'mensagens' => '1.3k',
];

public ?string $username = null;
/**
* Mock — Eventos vem de docs/plans/2026-09-22-api-mobile-jwt.md
* (feature "Eventos", ainda com gap de domínio pro check-in por QR).
* `statusToken` é um token de cor do tema (`primary` | `success`).
*
* @var list<array{title: string, when: string, status: string, statusToken: string}>
*/
public array $upcomingEvents = [
[
'title' => 'Workshop: Laravel na prática',
'when' => 'Qui, 25 Set · 19h',
'status' => 'Em breve',
'statusToken' => 'primary',
],
[
'title' => 'Mentoria coletiva de carreira',
'when' => 'Sáb, 27 Set · 10h',
'status' => 'Vagas abertas',
'statusToken' => 'success',
],
];

public function mount(): void
{
$response = Http::withToken((string) config('services.he4rt_api.poc_token'))
->get(config('services.he4rt_api.base_url').'/api/mobile/me');
/**
* Mock — post fixado da Timeline, com um trecho de código pra dar cara
* de comunidade dev. Vem de docs/plans/2026-09-22-api-mobile-jwt.md
* (feature "Timeline").
*
* @var array{author: string, timeAgo: string, body: string, codeFile: string, codeLang: string, codeLines: list<string>, tags: list<string>, likes: int, comments: int}
*/
public array $featuredPost = [
'author' => 'time He4rt',
'timeAgo' => 'há 2h',
'body' => 'Refatoramos o pool de conexões do Postgres no gateway da API do heartdevs.com.',
'codeFile' => 'config/database.php',
'codeLang' => 'php',
'codeLines' => [
"'pool' => ['min' => 5, 'max' => 50],",
'// timeout ajustado pra reduzir o P99',
],
'tags' => ['#backend', '#postgres', '#performance'],
'likes' => 84,
'comments' => 23,
];

if ($response->successful()) {
$this->status = 'ok';
$this->username = $response->json('username');
/**
* Mock — restante da Timeline, em formato compacto.
*
* @var list<array{title: string, author: string, timeAgo: string}>
*/
public array $latestPosts = [
[
'title' => 'Turma de mentoria de Setembro está com vagas abertas',
'author' => 'maria.dev',
'timeAgo' => 'há 5h',
],
[
'title' => 'Como fomos de 0 a 9 mil devs na comunidade',
'author' => 'time He4rt',
'timeAgo' => 'ontem',
],
];

return;
}
public function goToEventos(): void
{
$this->replace('/eventos');
}

$this->status = 'error';
public function goToTimeline(): void
{
$this->replace('/timeline');
}

public function goToDiscord(): void
{
Browser::open('https://discord.com/invite/he4rt');
}

public function navTitle(): string
{
return 'He4rt';
return 'Início';
}

public function render(): View
Expand Down
41 changes: 41 additions & 0 deletions app/NativeComponents/Perfil.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?php

declare(strict_types=1);

namespace App\NativeComponents;

use Illuminate\Support\Facades\Http;
use Illuminate\View\View;
use Native\Mobile\Edge\NativeComponent;

class Perfil extends NativeComponent
{
public string $apiStatus = 'loading';

public ?string $apiUsername = null;

public function mount(): void
{
$response = Http::withToken((string) config('services.he4rt_api.poc_token'))
->get(config('services.he4rt_api.base_url').'/api/mobile/me');

if ($response->successful()) {
$this->apiStatus = 'ok';
$this->apiUsername = $response->json('username');

return;
}

$this->apiStatus = 'error';
}

public function navTitle(): string
{
return 'Perfil';
}

public function render(): View
{
return view('native.perfil');
}
}
21 changes: 21 additions & 0 deletions app/NativeComponents/Timeline.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php

declare(strict_types=1);

namespace App\NativeComponents;

use Illuminate\View\View;
use Native\Mobile\Edge\NativeComponent;

class Timeline extends NativeComponent
{
public function navTitle(): string
{
return 'Timeline';
}

public function render(): View
{
return view('native.timeline');
}
}
42 changes: 42 additions & 0 deletions app/NativeLayouts/TabsLayout.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?php

declare(strict_types=1);

namespace App\NativeLayouts;

use App\Icons\Android;
use App\Icons\Ios;
use Native\Mobile\Edge\Layouts\Builders\NavBar;
use Native\Mobile\Edge\Layouts\Builders\Tab;
use Native\Mobile\Edge\Layouts\Builders\TabBar;
use Native\Mobile\Edge\Layouts\NativeLayout;
use Native\Mobile\Edge\NativeComponent;

/**
* Chrome for the app's main tab section: Início, Timeline, Eventos, Perfil.
* Attached via Route::nativeGroup(layout: self::class, ...) in routes/web.php.
*/
class TabsLayout extends NativeLayout
{
public function navBar(NativeComponent $screen): ?NavBar
{
return NavBar::make()
->titleView(view('native.partials.brand-title'))
->displayMode('inline');
}

public function tabBar(NativeComponent $screen): ?TabBar
{
return TabBar::make()
->activeColor(theme('primary'))
->add(Tab::link('Início', '/home', ios: Ios::HouseFill, android: Android::Home))
->add(Tab::link('Timeline', '/timeline', ios: Ios::BubbleLeftAndBubbleRightFill, android: Android::Forum))
->add(Tab::link('Eventos', '/eventos', ios: Ios::Calendar, android: Android::Event))
->add(Tab::link('Perfil', '/perfil', ios: Ios::PersonFill, android: Android::AccountCircle));
}

public function usesNativeChrome(): bool
{
return true;
}
}
2 changes: 1 addition & 1 deletion config/nativephp.php
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@
|
*/

'appearance' => env('NATIVEPHP_APPEARANCE', 'system'),
'appearance' => env('NATIVEPHP_APPEARANCE', 'dark'),

/*
|--------------------------------------------------------------------------
Expand Down
10 changes: 10 additions & 0 deletions resources/views/native/eventos.blade.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
@use('App\Icons\Ios')
@use('App\Icons\Android')

@include('native.partials.coming-soon', [
'icon' => 'calendar',
'iosIcon' => Ios::Calendar,
'androidIcon' => Android::Event,
'title' => 'Eventos chegando em breve',
'description' => "Workshops, mentorias e encontros da comunidade — com inscrição e check-in direto pelo app.",
])
Loading
Loading