panduan pengambilan foto

This commit is contained in:
kizadl 2026-05-20 11:12:33 +07:00
parent 86c4fb3189
commit 7c969b72de
4 changed files with 103 additions and 6 deletions

View File

@ -33,6 +33,7 @@
<!-- CTAs --> <!-- CTAs -->
<div class="flex flex-col sm:flex-row items-center justify-center gap-4 mb-16"> <div class="flex flex-col sm:flex-row items-center justify-center gap-4 mb-16">
<button <button
@click="scrollToScanner"
class="shimmer-btn bg-white text-zinc-950 hover:bg-zinc-200 rounded-full px-8 py-3 text-base font-medium shadow-lg shadow-white/10 flex items-center gap-2" class="shimmer-btn bg-white text-zinc-950 hover:bg-zinc-200 rounded-full px-8 py-3 text-base font-medium shadow-lg shadow-white/10 flex items-center gap-2"
> >
Mulai Klasifikasi Mulai Klasifikasi
@ -47,7 +48,7 @@
<!-- Social Proof --> <!-- Social Proof -->
<div class="flex flex-col items-center gap-4"> <div class="flex flex-col items-center gap-4">
<div class="flex items-center -space-x-3"> <!-- <div class="flex items-center -space-x-3">
<img <img
v-for="(avatar, index) in avatars" v-for="(avatar, index) in avatars"
:key="index" :key="index"
@ -56,9 +57,9 @@
class="w-10 h-10 rounded-full border-2 border-zinc-950 object-cover" class="w-10 h-10 rounded-full border-2 border-zinc-950 object-cover"
loading="lazy" loading="lazy"
/> />
</div> </div> -->
<p class="text-sm text-zinc-500"> <p class="text-sm text-zinc-500">
Telah digunakan oleh <span class="text-zinc-300 font-medium">2,000+</span> orang Telah digunakan <span class="text-zinc-300 font-medium">{{ totalClassifications ? totalClassifications.toLocaleString('id-ID') : '0' }}</span> kali
</p> </p>
</div> </div>
</div> </div>
@ -68,6 +69,14 @@
<script setup lang="ts"> <script setup lang="ts">
import { ArrowRight } from 'lucide-vue-next' import { ArrowRight } from 'lucide-vue-next'
defineProps<{
totalClassifications?: number
}>()
const scrollToScanner = () => {
document.getElementById('klasifikasi')?.scrollIntoView({ behavior: 'smooth' })
}
const avatars = [ const avatars = [
'/professional-headshot-1.png', '/professional-headshot-1.png',
'/professional-headshot-2.png', '/professional-headshot-2.png',

View File

@ -21,13 +21,23 @@
Unggah foto biji kopi Arabika Anda. Pastikan gambar jelas dan mendapatkan pencahayaan yang cukup untuk hasil terbaik. Unggah foto biji kopi Arabika Anda. Pastikan gambar jelas dan mendapatkan pencahayaan yang cukup untuk hasil terbaik.
</p> </p>
<div class="flex items-center gap-3"> <div class="flex flex-wrap items-center gap-3">
<div class="flex items-center gap-1.5 px-3 py-1.5 rounded-full bg-emerald-500/10 border border-emerald-500/20"> <div class="flex items-center gap-1.5 px-3 py-1.5 rounded-full bg-emerald-500/10 border border-emerald-500/20">
<div :class="['w-2 h-2 rounded-full bg-emerald-500', isLoading ? 'animate-ping' : 'animate-pulse']"></div> <div :class="['w-2 h-2 rounded-full bg-emerald-500', isLoading ? 'animate-ping' : 'animate-pulse']"></div>
<span class="text-[10px] font-bold text-emerald-500 uppercase tracking-wider"> <span class="text-[10px] font-bold text-emerald-500 uppercase tracking-wider">
{{ isLoading ? 'Processing...' : 'AI Model Ready' }} {{ isLoading ? 'Processing...' : 'AI Model Ready' }}
</span> </span>
</div> </div>
<button
@click="showGuideModal = true"
class="flex items-center gap-1.5 px-3 py-1.5 rounded-full bg-zinc-800/80 border border-zinc-700 hover:border-emerald-500/50 hover:bg-zinc-800 transition-all group"
>
<Info class="w-3.5 h-3.5 text-zinc-400 group-hover:text-emerald-400 transition-colors" />
<span class="text-[10px] font-bold text-zinc-400 group-hover:text-emerald-400 uppercase tracking-wider transition-colors">
Panduan Foto
</span>
</button>
</div> </div>
</div> </div>
@ -128,6 +138,77 @@
</div> </div>
</div> </div>
<!-- Modal Panduan -->
<transition
enter-active-class="transition duration-300 ease-out"
enter-from-class="opacity-0"
enter-to-class="opacity-100"
leave-active-class="transition duration-200 ease-in"
leave-from-class="opacity-100"
leave-to-class="opacity-0"
>
<div v-if="showGuideModal" class="fixed inset-0 z-[100] flex items-center justify-center p-4 bg-black/80 backdrop-blur-sm" @click="showGuideModal = false">
<div class="bg-zinc-900 border border-zinc-800 rounded-3xl max-w-3xl w-full p-6 sm:p-8 relative overflow-hidden shadow-2xl" @click.stop>
<button @click="showGuideModal = false" class="absolute top-4 right-4 text-zinc-400 hover:text-white bg-zinc-800 hover:bg-zinc-700 p-2 rounded-full transition-colors z-10">
<X class="w-5 h-5" />
</button>
<div class="flex items-center gap-3 mb-8 pr-8">
<div class="p-2.5 rounded-xl bg-emerald-500/10">
<Info class="w-6 h-6 text-emerald-500" />
</div>
<h3 class="text-2xl font-bold text-white font-display">Panduan Pengambilan Foto</h3>
</div>
<div class="grid md:grid-cols-2 gap-8 items-center">
<div class="space-y-4">
<div class="bg-black/50 rounded-2xl overflow-hidden border border-zinc-800 relative group">
<img src="/pict_example.jpg" alt="Contoh Foto Benar" class="w-full h-auto aspect-video object-cover" />
<div class="absolute inset-0 border-2 border-emerald-500/0 group-hover:border-emerald-500/50 rounded-2xl transition-colors pointer-events-none"></div>
</div>
<div class="flex items-center gap-2 text-emerald-400 text-sm font-medium">
<div class="w-2 h-2 rounded-full bg-emerald-400 animate-pulse"></div>
Contoh Foto yang Benar
</div>
</div>
<div class="flex flex-col justify-center space-y-6">
<div>
<h4 class="text-lg font-bold text-white mb-3 flex items-center gap-2">
<span class="text-emerald-500">Tips</span> agar hasil akurat:
</h4>
<ul class="space-y-3">
<li class="flex items-start gap-3">
<div class="min-w-[24px] h-6 rounded-full bg-emerald-500/10 text-emerald-500 flex items-center justify-center text-xs font-bold mt-0.5 border border-emerald-500/20">1</div>
<p class="text-zinc-300 text-sm leading-relaxed">Pastikan objek biji kopi <strong>fokus</strong> dan tidak buram (blur).</p>
</li>
<li class="flex items-start gap-3">
<div class="min-w-[24px] h-6 rounded-full bg-emerald-500/10 text-emerald-500 flex items-center justify-center text-xs font-bold mt-0.5 border border-emerald-500/20">2</div>
<p class="text-zinc-300 text-sm leading-relaxed">Gunakan <strong>pencahayaan yang cukup</strong> (cahaya matahari/lampu terang) agar tekstur dan warna jelas.</p>
</li>
<li class="flex items-start gap-3">
<div class="min-w-[24px] h-6 rounded-full bg-emerald-500/10 text-emerald-500 flex items-center justify-center text-xs font-bold mt-0.5 border border-emerald-500/20">3</div>
<p class="text-zinc-300 text-sm leading-relaxed">Hindari <strong>bayangan yang terlalu gelap</strong> atau pantulan cahaya yang menyilaukan.</p>
</li>
<li class="flex items-start gap-3">
<div class="min-w-[24px] h-6 rounded-full bg-emerald-500/10 text-emerald-500 flex items-center justify-center text-xs font-bold mt-0.5 border border-emerald-500/20">4</div>
<p class="text-zinc-300 text-sm leading-relaxed">Ambil foto dari <strong>jarak yang pas</strong>. Biji kopi harus terlihat jelas secara keseluruhan.</p>
</li>
</ul>
</div>
</div>
</div>
<div class="mt-8 pt-6 border-t border-zinc-800 flex justify-end">
<button @click="showGuideModal = false" class="px-6 py-2.5 bg-emerald-600 hover:bg-emerald-500 text-white font-bold rounded-xl transition-colors">
Mengerti
</button>
</div>
</div>
</div>
</transition>
</section> </section>
</template> </template>
@ -135,12 +216,13 @@
import { ref, computed } from 'vue' import { ref, computed } from 'vue'
import { router } from '@inertiajs/vue3' import { router } from '@inertiajs/vue3'
import { route } from 'ziggy-js' import { route } from 'ziggy-js'
import { Upload, Plus, X, Loader2, Bean } from 'lucide-vue-next' import { Upload, Plus, X, Loader2, Bean, Info } from 'lucide-vue-next'
const imagePreview = ref<string | null>(null) const imagePreview = ref<string | null>(null)
const selectedFile = ref<File | null>(null) const selectedFile = ref<File | null>(null)
const predictionResult = ref<{ label: string, confidence: string, details?: string, status?: string } | null>(null) const predictionResult = ref<{ label: string, confidence: string, details?: string, status?: string } | null>(null)
const isLoading = ref(false) const isLoading = ref(false)
const showGuideModal = ref(false)
const statusInfo = computed(() => { const statusInfo = computed(() => {
if (!predictionResult.value) return null if (!predictionResult.value) return null

View File

@ -1,7 +1,7 @@
<template> <template>
<div class="bg-background text-foreground min-h-screen"> <div class="bg-background text-foreground min-h-screen">
<Navbar /> <Navbar />
<Hero /> <Hero :total-classifications="totalClassifications" />
<Logo /> <Logo />
<Scanner /> <Scanner />
<Keunggulan /> <Keunggulan />
@ -21,4 +21,8 @@ import Scanner from '@/components/public/Scanner.vue'
import Teknologi from '@/components/public/Teknologi.vue' import Teknologi from '@/components/public/Teknologi.vue'
import FAQ from '@/components/public/FAQ.vue' import FAQ from '@/components/public/FAQ.vue'
import FinalCta from '@/components/public/FinalCta.vue' import FinalCta from '@/components/public/FinalCta.vue'
defineProps<{
totalClassifications?: number
}>()
</script> </script>

View File

@ -6,6 +6,7 @@
use App\Http\Controllers\Admin\DashboardController; use App\Http\Controllers\Admin\DashboardController;
use App\Http\Controllers\Public\ClassificationController; use App\Http\Controllers\Public\ClassificationController;
use App\Http\Controllers\Admin\ClassificationController as AdminClassificationController; use App\Http\Controllers\Admin\ClassificationController as AdminClassificationController;
use App\Models\Classification;
Route::get('dashboard', function () { Route::get('dashboard', function () {
if (auth()->user()->role === 'admin') { if (auth()->user()->role === 'admin') {
@ -17,6 +18,7 @@
Route::get('/', function () { Route::get('/', function () {
return inertia('public/Home', [ return inertia('public/Home', [
'canRegister' => Features::enabled(Features::registration()), 'canRegister' => Features::enabled(Features::registration()),
'totalClassifications' => Classification::count(),
]); ]);
})->name('home'); })->name('home');