add testimoni
This commit is contained in:
parent
74840a4fcb
commit
d550571217
@ -9,13 +9,14 @@ use App\Models\Review;
|
|||||||
class ReviewController extends Controller
|
class ReviewController extends Controller
|
||||||
{
|
{
|
||||||
// Ambil semua ulasan
|
// Ambil semua ulasan
|
||||||
public function index()
|
public function index()
|
||||||
{
|
{
|
||||||
$reviews = Review::all();
|
$reviews = Review::all();
|
||||||
return view('admin.reviews.index', compact('reviews'));
|
return response()->json($reviews, 200);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Simpan ulasan baru
|
// Simpan ulasan baru
|
||||||
public function store(Request $request)
|
public function store(Request $request)
|
||||||
{
|
{
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
<!-- Layout gambar + teks -->
|
<!-- Layout gambar + teks -->
|
||||||
<div class="about-layout">
|
<div class="about-layout">
|
||||||
<div class="about-image">
|
<div class="about-image">
|
||||||
<img src="/logo1.png" alt="Tentang Kami - Undangan Digital" />
|
<img src="/rectangle.png" alt="Tentang Kami - Undangan Digital" />
|
||||||
</div>
|
</div>
|
||||||
<div class="about-text">
|
<div class="about-text">
|
||||||
<p>
|
<p>
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
<header class="main-header">
|
<header class="main-header">
|
||||||
<nav class="container">
|
<nav class="container">
|
||||||
<div class="logo">
|
<div class="logo">
|
||||||
<NuxtLink to="/" class="logo-link"> <img src="/ABBAUF.png" alt="Abbauf Tech Logo" class="logo-icon">
|
<NuxtLink to="/" class="logo-link"> <img src="/abbauflogo.png" alt="Abbauf Tech Logo" class="logo-icon">
|
||||||
<span>ABBAUF TECH</span>
|
<span>ABBAUF TECH</span>
|
||||||
</NuxtLink>
|
</NuxtLink>
|
||||||
</div>
|
</div>
|
||||||
@ -58,7 +58,7 @@ const navLinks = ref([
|
|||||||
}
|
}
|
||||||
|
|
||||||
.logo-icon {
|
.logo-icon {
|
||||||
width: 40px;
|
width: 50px;
|
||||||
margin-right: 10px;
|
margin-right: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="w-full lg:w-1/2">
|
<div class="w-full lg:w-1/2">
|
||||||
<img src="/logo2.png" alt="Tampilan Undangan Digital di Ponsel" class="mx-auto max-w-full">
|
<img src="/iphone.png" alt="Tampilan Undangan Digital di Ponsel" class="mx-auto max-w-full">
|
||||||
<div class="mt-6 text-center italic text-gray-500">
|
<div class="mt-6 text-center italic text-gray-500">
|
||||||
<p>"Abadikan momen indahmu dengan undangan digital yang elegan."</p>
|
<p>"Abadikan momen indahmu dengan undangan digital yang elegan."</p>
|
||||||
<p>"Satu aplikasi untuk semua momen spesialmu."</p>
|
<p>"Satu aplikasi untuk semua momen spesialmu."</p>
|
||||||
|
@ -4,66 +4,264 @@
|
|||||||
<h2 class="text-4xl font-extrabold text-gray-800 mb-2">
|
<h2 class="text-4xl font-extrabold text-gray-800 mb-2">
|
||||||
Apa Kata Mereka?
|
Apa Kata Mereka?
|
||||||
</h2>
|
</h2>
|
||||||
<p class="text-lg text-gray-600 mb-16">
|
<p class="text-lg text-gray-600 mb-10">
|
||||||
Kisah sukses dari para pengguna yang telah mempercayakan momen spesialnya kepada kami.
|
Kisah sukses dari para pengguna yang telah mempercayakan momen spesialnya kepada kami.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<div class="grid grid-cols-1 gap-8 md:grid-cols-2 lg:grid-cols-3">
|
<!-- CSS Marquee Scroll -->
|
||||||
|
<div class="marquee-container mb-10">
|
||||||
|
<div class="marquee-content" :style="{ '--total-cards': testimonials?.length || 0 }">
|
||||||
|
<!-- Render original cards -->
|
||||||
<div
|
<div
|
||||||
v-for="testimonial in testimonials"
|
v-for="testimonial in testimonials"
|
||||||
:key="testimonial.id"
|
:key="`original-${testimonial.id}`"
|
||||||
class="flex flex-col rounded-xl bg-white p-8 text-left shadow-lg transition-transform duration-300 hover:-translate-y-2 hover:shadow-2xl"
|
class="testimonial-card"
|
||||||
|
@click="previewModal = testimonial"
|
||||||
>
|
>
|
||||||
|
<!-- Rating -->
|
||||||
<div class="mb-4 flex items-center">
|
<div class="mb-4 flex items-center">
|
||||||
<svg v-for="n in 5" :key="n" class="h-5 w-5" :class="n <= testimonial.rating ? 'text-yellow-400' : 'text-gray-300'" fill="currentColor" viewBox="0 0 20 20"><path d="M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.371 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.54 1.118l-2.8-2.034a1 1 0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1 1 0 00.951-.69l1.07-3.292z"></path></svg>
|
<svg
|
||||||
|
v-for="n in 5"
|
||||||
|
:key="n"
|
||||||
|
class="h-5 w-5"
|
||||||
|
:class="n <= Number(testimonial.rating) ? 'text-yellow-400' : 'text-gray-300'"
|
||||||
|
fill="currentColor"
|
||||||
|
viewBox="0 0 20 20"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07
|
||||||
|
3.292a1 1 0 00.95.69h3.462c.969 0 1.371
|
||||||
|
1.24.588 1.81l-2.8 2.034a1 1 0
|
||||||
|
00-.364 1.118l1.07 3.292c.3.921-.755
|
||||||
|
1.688-1.54 1.118l-2.8-2.034a1 1
|
||||||
|
0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1
|
||||||
|
1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1
|
||||||
|
1 0 00.951-.69l1.07-3.292z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p class="mb-6 flex-grow text-gray-600 italic">"{{ testimonial.text }}"</p>
|
<!-- Pesan -->
|
||||||
|
<p class="mb-6 flex-grow text-gray-600 italic line-clamp-3 min-h-[72px] break-words">
|
||||||
|
"{{ testimonial.message }}"
|
||||||
|
</p>
|
||||||
|
|
||||||
<div class="flex items-center">
|
<!-- User Info -->
|
||||||
<img class="h-12 w-12 rounded-full object-cover" :src="testimonial.avatar" :alt="testimonial.name">
|
<div>
|
||||||
<div class="ml-4">
|
|
||||||
<h4 class="font-bold text-gray-800">{{ testimonial.name }}</h4>
|
<h4 class="font-bold text-gray-800">{{ testimonial.name }}</h4>
|
||||||
<p class="text-sm text-gray-500">{{ testimonial.role }}</p>
|
<p class="text-sm text-gray-500">{{ testimonial.city }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Render clone untuk seamless loop -->
|
||||||
|
<div
|
||||||
|
v-for="testimonial in testimonials"
|
||||||
|
:key="`clone-${testimonial.id}`"
|
||||||
|
class="testimonial-card"
|
||||||
|
@click="previewModal = testimonial"
|
||||||
|
>
|
||||||
|
<!-- Rating -->
|
||||||
|
<div class="mb-4 flex items-center">
|
||||||
|
<svg
|
||||||
|
v-for="n in 5"
|
||||||
|
:key="n"
|
||||||
|
class="h-5 w-5"
|
||||||
|
:class="n <= Number(testimonial.rating) ? 'text-yellow-400' : 'text-gray-300'"
|
||||||
|
fill="currentColor"
|
||||||
|
viewBox="0 0 20 20"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07
|
||||||
|
3.292a1 1 0 00.95.69h3.462c.969 0 1.371
|
||||||
|
1.24.588 1.81l-2.8 2.034a1 1 0
|
||||||
|
00-.364 1.118l1.07 3.292c.3.921-.755
|
||||||
|
1.688-1.54 1.118l-2.8-2.034a1 1
|
||||||
|
0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1
|
||||||
|
1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1
|
||||||
|
1 0 00.951-.69l1.07-3.292z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Pesan -->
|
||||||
|
<p class="mb-6 flex-grow text-gray-600 italic line-clamp-3 min-h-[72px] break-words">
|
||||||
|
"{{ testimonial.message }}"
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<!-- User Info -->
|
||||||
|
<div>
|
||||||
|
<h4 class="font-bold text-gray-800">{{ testimonial.name }}</h4>
|
||||||
|
<p class="text-sm text-gray-500">{{ testimonial.city }}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Tombol Berikan Ulasan -->
|
||||||
|
<button
|
||||||
|
@click="openModal = true"
|
||||||
|
class="px-6 py-3 rounded-lg bg-blue-500 text-white font-semibold shadow hover:bg-blue-700 transition"
|
||||||
|
>
|
||||||
|
Berikan Ulasan
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Modal Form -->
|
||||||
|
<div
|
||||||
|
v-if="openModal"
|
||||||
|
class="fixed inset-0 z-50 flex items-center justify-center bg-gray-800/30"
|
||||||
|
>
|
||||||
|
<div class="bg-white rounded-lg shadow-xl w-full max-w-lg p-6 relative">
|
||||||
|
<button
|
||||||
|
@click="openModal = false"
|
||||||
|
class="absolute top-3 right-3 text-gray-500 hover:text-gray-800"
|
||||||
|
>
|
||||||
|
✕
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<h3 class="text-xl font-bold mb-4 text-gray-800">Tulis Ulasan</h3>
|
||||||
|
|
||||||
|
<form @submit.prevent="submitReview">
|
||||||
|
<div class="mb-4 text-left">
|
||||||
|
<label class="block text-sm font-medium mb-1">Nama</label>
|
||||||
|
<input v-model="form.name" type="text" class="w-full rounded border px-3 py-2" required />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mb-4 text-left">
|
||||||
|
<label class="block text-sm font-medium mb-1">Kota</label>
|
||||||
|
<input v-model="form.city" type="text" class="w-full rounded border px-3 py-2" required />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mb-4 text-left">
|
||||||
|
<label class="block text-sm font-medium mb-1">Rating</label>
|
||||||
|
<select v-model="form.rating" class="w-full rounded border px-3 py-2" required>
|
||||||
|
<option value="">Pilih rating</option>
|
||||||
|
<option v-for="n in 5" :key="n" :value="n">{{ n }} ⭐</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mb-4 text-left">
|
||||||
|
<label class="block text-sm font-medium mb-1">Pesan</label>
|
||||||
|
<textarea v-model="form.message" class="w-full rounded border px-3 py-2" rows="3" required />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button
|
||||||
|
type="submit"
|
||||||
|
class="w-full bg-blue-600 text-white py-2 rounded-lg font-semibold hover:bg-blue-700 transition"
|
||||||
|
>
|
||||||
|
Kirim Ulasan
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Modal Preview -->
|
||||||
|
<div
|
||||||
|
v-if="previewModal"
|
||||||
|
class="fixed inset-0 z-50 flex items-center justify-center bg-gray-800/30"
|
||||||
|
>
|
||||||
|
<div class="bg-white rounded-lg shadow-xl w-full max-w-lg p-6 relative">
|
||||||
|
<button
|
||||||
|
@click="previewModal = null"
|
||||||
|
class="absolute top-3 right-3 text-gray-500 hover:text-gray-800"
|
||||||
|
>
|
||||||
|
✕
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<h3 class="text-xl font-bold mb-4 text-gray-800">Ulasan Lengkap</h3>
|
||||||
|
<p class="text-gray-600 italic mb-4 whitespace-pre-line break-words">
|
||||||
|
"{{ previewModal.message }}"
|
||||||
|
</p>
|
||||||
|
<h4 class="font-bold text-gray-800">{{ previewModal.name }}</h4>
|
||||||
|
<p class="text-sm text-gray-500">{{ previewModal.city }}</p>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue'
|
||||||
|
|
||||||
const testimonials = ref([
|
const { data: testimonials, refresh } = await useFetch('http://localhost:8000/api/reviews')
|
||||||
{
|
|
||||||
id: 1,
|
const openModal = ref(false)
|
||||||
name: 'Rizky & Anisa',
|
const previewModal = ref(null)
|
||||||
role: 'Pengantin Baru',
|
|
||||||
avatar: 'https://i.pravatar.cc/100?u=rizky',
|
const form = ref({
|
||||||
rating: 5,
|
name: '',
|
||||||
text: 'Desainnya elegan dan modern! Proses pembuatannya juga cepat banget. Semua tamu memuji undangannya. Terima kasih Abbauf Tech!'
|
city: '',
|
||||||
},
|
rating: '',
|
||||||
{
|
message: ''
|
||||||
id: 2,
|
})
|
||||||
name: 'Budi Santoso',
|
|
||||||
role: 'Event Organizer',
|
// Submit review
|
||||||
avatar: 'https://i.pravatar.cc/100?u=budi',
|
const submitReview = async () => {
|
||||||
rating: 5,
|
try {
|
||||||
text: 'Sebagai EO, kami butuh platform yang efisien dan hasilnya premium. Abbauf Tech menjawab semua kebutuhan itu. Klien kami sangat puas.'
|
await $fetch('http://localhost:8000/api/reviews', {
|
||||||
},
|
method: 'POST',
|
||||||
{
|
body: form.value
|
||||||
id: 3,
|
})
|
||||||
name: 'Citra Lestari',
|
form.value = { name: '', city: '', rating: '', message: '' }
|
||||||
role: 'Ulang Tahun Anak',
|
openModal.value = false
|
||||||
avatar: 'https://i.pravatar.cc/100?u=citra',
|
await refresh()
|
||||||
rating: 4,
|
} catch (err) {
|
||||||
text: 'Fitur RSVP dan pengingat sangat membantu. Tema-tema ulang tahunnya juga lucu dan bisa dikustomisasi. Sangat direkomendasikan!'
|
console.error('Gagal simpan ulasan:', err)
|
||||||
},
|
}
|
||||||
]);
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
/* Kosong, semua diatur oleh Tailwind */
|
/* Marquee Container */
|
||||||
|
.marquee-container {
|
||||||
|
overflow: hidden;
|
||||||
|
padding: 1rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Marquee Content - Contains all cards */
|
||||||
|
.marquee-content {
|
||||||
|
display: flex;
|
||||||
|
gap: 1.5rem;
|
||||||
|
animation: marquee calc(var(--total-cards) * 8s) linear infinite;
|
||||||
|
width: max-content;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Individual testimonial card */
|
||||||
|
.testimonial-card {
|
||||||
|
flex-shrink: 0;
|
||||||
|
width: 24rem; /* 384px = w-96 */
|
||||||
|
border-radius: 0.75rem;
|
||||||
|
background: white;
|
||||||
|
padding: 2rem;
|
||||||
|
text-align: left;
|
||||||
|
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
|
||||||
|
transition: transform 300ms, box-shadow 300ms;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.testimonial-card:hover {
|
||||||
|
transform: translateY(-0.5rem);
|
||||||
|
box-shadow: 0 25px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Marquee animation */
|
||||||
|
@keyframes marquee {
|
||||||
|
0% {
|
||||||
|
transform: translateX(0);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: translateX(-50%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Pause animation on hover */
|
||||||
|
.marquee-container:hover .marquee-content {
|
||||||
|
animation-play-state: paused;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Responsive adjustments */
|
||||||
|
@media (max-width: 640px) {
|
||||||
|
.testimonial-card {
|
||||||
|
width: 20rem; /* Smaller on mobile */
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
BIN
proyek-frontend/public/Rectangle.png
Normal file
BIN
proyek-frontend/public/Rectangle.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 228 KiB |
BIN
proyek-frontend/public/abbauflogo.png
Normal file
BIN
proyek-frontend/public/abbauflogo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 10 KiB |
BIN
proyek-frontend/public/iphone.png
Normal file
BIN
proyek-frontend/public/iphone.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 233 KiB |
Loading…
Reference in New Issue
Block a user