Skip to content

Commit

Permalink
#28 - contact page (#136)
Browse files Browse the repository at this point in the history
* #28 - feat: added contact page

* #28 - feat: added empty state

* #28 - fix: code review fixes
  • Loading branch information
kamilpiech97 authored Aug 28, 2024
1 parent 86b0128 commit 2f34f50
Show file tree
Hide file tree
Showing 14 changed files with 179 additions and 54 deletions.
23 changes: 23 additions & 0 deletions app/DTOs/ContactInfoData.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php

declare(strict_types=1);

namespace Keating\DTOs;

use Keating\Models\ContactInfo;

readonly class ContactInfoData
{
public function __construct(
public string $label,
public string $identifier,
) {}

public static function fromModel(ContactInfo $contactInfo): self
{
return new self(
label: $contactInfo->label,
identifier: $contactInfo->identifier,
);
}
}
16 changes: 0 additions & 16 deletions app/Enums/Icons.php

This file was deleted.

7 changes: 1 addition & 6 deletions app/Http/Controllers/Dashboard/ContactInfoController.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,8 @@
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Inertia\Response;
use Keating\Enums\Icons;
use Keating\Http\Requests\ContactInfoRequest;
use Keating\Models\ContactInfo;
use Spatie\LaravelOptions\Options;

class ContactInfoController
{
Expand All @@ -29,9 +27,7 @@ public function index(Request $request): Response

public function create(): Response
{
return inertia("Dashboard/ContactInfo/Create", [
"icons" => Options::forEnum(Icons::class)->toArray(),
]);
return inertia("Dashboard/ContactInfo/Create");
}

public function store(ContactInfoRequest $request): RedirectResponse
Expand All @@ -47,7 +43,6 @@ public function edit(ContactInfo $contactInfo): Response
{
return inertia("Dashboard/ContactInfo/Edit", [
"contactInfo" => $contactInfo,
"icons" => Options::forEnum(Icons::class)->toArray(),
]);
}

Expand Down
30 changes: 30 additions & 0 deletions app/Http/Controllers/Public/ContactController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

declare(strict_types=1);

namespace Keating\Http\Controllers\Public;

use Inertia\Response;
use Keating\DTOs\ContactInfoData;
use Keating\Models\ContactInfo;
use Keating\Models\Setting;

class ContactController
{
public function __invoke(): Response
{
/** @var Setting $settings */
$settings = Setting::query()->first();
$contactInfos = ContactInfo::query()->get();

return inertia("Public/Contact", [
"title" => $settings->teacher_titles,
"name" => $settings->teacher_name,
"email" => $settings->teacher_email,
"department" => $settings->department_name,
"university" => $settings->university_name,
"universityLogo" => asset("cwup-full.png"),
"contactInfos" => $contactInfos->map(fn(ContactInfo $contactInfo): ContactInfoData => ContactInfoData::fromModel($contactInfo)),
]);
}
}
3 changes: 0 additions & 3 deletions app/Http/Requests/ContactInfoRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@
namespace Keating\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rules\Enum;
use Keating\Enums\Icons;

class ContactInfoRequest extends FormRequest
{
Expand All @@ -15,7 +13,6 @@ public function rules(): array
return [
"label" => ["required", "string", "max:255"],
"identifier" => ["required", "string", "max:255"],
"icon" => ["required", new Enum(Icons::class)],
];
}
}
5 changes: 2 additions & 3 deletions app/Models/ContactInfo.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,8 @@

/**
* @property string $id
* @property string $email
* @property string $github_handle
* @property string $alternative_channel
* @property string $label
* @property string $identifier
* @property Carbon $created_at
* @property Carbon $updated_at
*/
Expand Down
2 changes: 0 additions & 2 deletions database/factories/ContactInfoFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
namespace Database\Factories;

use Illuminate\Database\Eloquent\Factories\Factory;
use Keating\Enums\Icons;
use Keating\Models\ContactInfo;

/**
Expand All @@ -18,7 +17,6 @@ public function definition(): array
return [
"label" => fake()->domainWord(),
"identifier" => fake()->url(),
"icon" => fake()->randomElement(Icons::class),
];
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php

declare(strict_types=1);

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class() extends Migration {
public function up(): void
{
Schema::table("contact_infos", function (Blueprint $table): void {
$table->dropColumn("icon");
});
}

public function down(): void
{
Schema::table("contact_infos", function (Blueprint $table): void {
$table->string("icon")->nullable();
});
}
};
8 changes: 0 additions & 8 deletions resources/js/Pages/Dashboard/ContactInfo/Create.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import SubmitButton from '@/Shared/Components/Buttons/SubmitButton.vue'
import FormGroup from '@/Shared/Forms/FormGroup.vue'
import FormLabel from '@/Shared/Forms/FormLabel.vue'
import TextInput from '@/Shared/Forms/TextInput.vue'
import Select from '@/Shared/Forms/Select.vue'
import { useForm } from '@inertiajs/inertia-vue3'
import FormError from '@/Shared/Forms/FormError.vue'
import ManagementHeader from '@/Shared/Components/ManagementHeader.vue'
Expand Down Expand Up @@ -63,13 +62,6 @@ function createContactInfo() {
<TextInput id="identifier" v-model="form.identifier" :error="form.errors.identifier" autocomplete="off" />
<FormError :error="form.errors.identifier" />
</FormGroup>
<FormGroup>
<FormLabel for="icon">
Ikona
</FormLabel>
<Select id="icon" v-model="form.icon" :error="form.errors.icon" :options="icons" label="label" item-value="value" />
<FormError :error="form.errors.icon" />
</FormGroup>
<div class="mt-4 flex justify-end">
<SubmitButton>
Utwórz
Expand Down
8 changes: 0 additions & 8 deletions resources/js/Pages/Dashboard/ContactInfo/Edit.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import SubmitButton from '@/Shared/Components/Buttons/SubmitButton.vue'
import FormGroup from '@/Shared/Forms/FormGroup.vue'
import FormLabel from '@/Shared/Forms/FormLabel.vue'
import TextInput from '@/Shared/Forms/TextInput.vue'
import Select from '@/Shared/Forms/Select.vue'
import { useForm } from '@inertiajs/inertia-vue3'
import FormError from '@/Shared/Forms/FormError.vue'
import ManagementHeader from '@/Shared/Components/ManagementHeader.vue'
Expand Down Expand Up @@ -64,13 +63,6 @@ function updateContactInfo() {
<TextInput id="identifier" v-model="form.identifier" :error="form.errors.identifier" autocomplete="off" />
<FormError :error="form.errors.identifier" />
</FormGroup>
<FormGroup>
<FormLabel for="icon">
Ikona
</FormLabel>
<Select id="icon" v-model="form.icon" :error="form.errors.icon" :options="icons" label="label" item-value="value" />
<FormError :error="form.errors.icon" />
</FormGroup>
<div class="mt-4 flex justify-end">
<SubmitButton>
Zapisz
Expand Down
69 changes: 69 additions & 0 deletions resources/js/Pages/Public/Contact.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
<script setup>
import PublicLayout from '@/Layouts/PublicLayout.vue'
import BackgroundGrid from '@/Components/BackgroundGrid.vue'
import SectionHeader from '@/Components/SectionHeader.vue'
import { Head } from '@inertiajs/inertia-vue3'
import ContactItem from '@/Shared/Components/ContactItem.vue'
import { NoSymbolIcon } from '@heroicons/vue/24/outline'
defineProps({
title: String,
name: String,
email: String,
department: String,
university: String,
universityLogo: String,
sectionSettings: Object,
about: Array,
counters: Array,
contactInfos: Array,
})
</script>

<template>
<Head title="Kontakt" />

<PublicLayout>
<div class="relative isolate bg-white">
<BackgroundGrid />
<div class="py-24 sm:py-32">
<div class="mx-auto max-w-7xl px-6 lg:px-8">
<SectionHeader>
<template #header>
Kontakt
</template>
<template #subheader>
Informacje kontaktowe.
</template>
</SectionHeader>
<img src="/cwup.png" alt="" class="pointer-events-none absolute right-0 z-0 hidden w-1/2 opacity-10 lg:mt-16 lg:block xl:mt-10 2xl:mt-0">
<div class="mx-auto mt-10 border-t border-gray-200 pt-10 sm:mt-16 sm:pt-16 lg:mx-0 lg:max-w-none lg:grid-cols-3">
<div class="mx-auto max-w-7xl text-center lg:mx-0 lg:flex-auto ">
<div v-if="email" class="mx-auto max-w-2xl py-6 text-left lg:mx-0 xl:py-3">
<label class="text-sm">
E-mail
</label>
<a :href="'mailto:' + email"
class="flex w-full items-center text-center text-xl font-bold tracking-tight text-gray-900 sm:text-2xl"
>
{{ email.split('@')[0] }}
<span class="font-normal">@{{ email.split('@')[1] }}</span>
</a>
</div>
<div v-for="(contactInfo, index) in contactInfos" :key="index" class="mx-auto flex max-w-2xl py-6 lg:mx-0 xl:py-3">
<ContactItem :contact="contactInfo" />
</div>

<div v-if="!email && contactInfos.length === 0" class="text-center">
<NoSymbolIcon class="mx-auto size-12 text-gray-400" />
<h3 class="mt-2 text-sm font-semibold text-gray-900">
Brak danych kontaktowych
</h3>
</div>
</div>
</div>
</div>
</div>
</div>
</PublicLayout>
</template>
29 changes: 29 additions & 0 deletions resources/js/Shared/Components/ContactItem.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<script setup>
defineProps({
contact: Object,
})
const isMailable = (contact) => {
return contact.identifier.includes('@')
}
</script>

<template>
<div class="text-left">
<label class="text-sm">
{{ contact.label }}
</label>
<a v-if="isMailable(contact)"
:href="'mailto:' + contact.identifier"
class="flex w-full items-center justify-center text-center text-xl font-bold tracking-tight text-gray-900 sm:text-2xl"
>
{{ contact.identifier }}
</a>
<a v-else
:href="contact.identifier"
class="flex w-full items-center justify-center text-center text-xl font-bold tracking-tight text-gray-900 sm:text-2xl"
>
{{ contact.identifier }}
</a>
</div>
</template>
2 changes: 2 additions & 0 deletions routes/web.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
use Keating\Http\Controllers\Dashboard\SemesterController;
use Keating\Http\Controllers\Dashboard\SettingController;
use Keating\Http\Controllers\Dashboard\StudentController;
use Keating\Http\Controllers\Public\ContactController;
use Keating\Http\Controllers\Public\CourseController as PublicCourseController;
use Keating\Http\Controllers\Public\GradeController as PublicGradeController;
use Keating\Http\Controllers\Public\HomeController;
Expand All @@ -32,6 +33,7 @@
Route::get("/oceny/{semester?}/{course?}/{group?}/{index?}", PublicGradeController::class);
Route::get("/kursy", [PublicCourseController::class, "index"]);
Route::get("/kursy/{slug}", [PublicCourseController::class, "get"]);
Route::get("/kontakt", ContactController::class);

Route::middleware("guest")->group(function (): void {
Route::get("/login", [LoginController::class, "create"])->name("login");
Expand Down
8 changes: 0 additions & 8 deletions tests/Feature/ContactInfoTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Str;
use Keating\Enums\Icons;
use Keating\Models\ContactInfo;
use Keating\Models\User;
use Tests\TestCase;
Expand All @@ -30,7 +29,6 @@ public function testContactInfoCanBeCreated(): void
$this->post("/dashboard/contact-infos", [
"label" => "karol.zygadlo@collegiumwitelona.pl",
"identifier" => "mailto:karol.zygadlo@collegiumwitelona.pl",
"icon" => Icons::AtSymbol->value,
])->assertSessionHasNoErrors();

$this->assertDatabaseCount("contact_infos", 1);
Expand All @@ -43,19 +41,16 @@ public function testContactInfoCanBeUpdated(): void
$this->assertDatabaseMissing("contact_infos", [
"label" => "karol.zygadlo@collegiumwitelona.pl",
"identifier" => "mailto:karol.zygadlo@collegiumwitelona.pl",
"icon" => Icons::AtSymbol->value,
]);

$this->patch("/dashboard/contact-infos/{$contactInfo->id}", [
"label" => "karol.zygadlo@collegiumwitelona.pl",
"identifier" => "mailto:karol.zygadlo@collegiumwitelona.pl",
"icon" => Icons::AtSymbol->value,
])->assertSessionHasNoErrors();

$this->assertDatabaseHas("contact_infos", [
"label" => "karol.zygadlo@collegiumwitelona.pl",
"identifier" => "mailto:karol.zygadlo@collegiumwitelona.pl",
"icon" => "at-symbol",
]);
}

Expand All @@ -64,11 +59,9 @@ public function testContactInfoCannotBeCreatedWithInvalidData(): void
$this->post("/dashboard/contact-infos", [
"label" => Str::random(256),
"identifier" => Str::random(256),
"icon" => "test",
])->assertSessionHasErrors([
"label",
"identifier",
"icon",
]);

$this->assertDatabaseCount("contact_infos", 0);
Expand All @@ -79,7 +72,6 @@ public function testContactInfoCannotBeCreatedWithoutData(): void
$this->post("/dashboard/contact-infos", [])->assertSessionHasErrors([
"label",
"identifier",
"icon",
]);

$this->assertDatabaseCount("contact_infos", 0);
Expand Down

0 comments on commit 2f34f50

Please sign in to comment.