| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127 |
- <template>
- <Teleport to="body">
- <Transition
- enter-active-class="transition duration-200"
- enter-from-class="opacity-0"
- enter-to-class="opacity-100"
- leave-active-class="transition duration-150"
- leave-from-class="opacity-100"
- leave-to-class="opacity-0"
- >
- <div v-if="isOpen" class="fixed inset-0 z-[100] flex items-center justify-center p-4 sm:p-6">
- <!-- Backdrop -->
- <div class="absolute inset-0 bg-background/80 backdrop-blur-sm" />
- <!-- Modal -->
- <div
- v-motion
- :initial="{ opacity: 0, scale: 0.9, y: 20 }"
- :enter="{ opacity: 1, scale: 1, y: 0 }"
- class="relative w-full max-w-lg bg-card/90 border border-border/50 rounded-3xl shadow-2xl overflow-hidden backdrop-blur-xl"
- >
- <div class="absolute top-0 inset-x-0 h-1 bg-gradient-to-r from-primary/50 via-primary to-primary/50" />
- <div class="p-8">
- <div class="text-center mb-8">
- <div class="inline-flex items-center justify-center w-16 h-16 rounded-2xl bg-primary/10 text-primary mb-4">
- <MapPin class="w-8 h-8" />
- </div>
- <h2 class="text-2xl font-bold font-display mb-2">
- {{ t("profile.complete_title") || "Complete Your Profile" }}
- </h2>
- <p class="text-muted-foreground text-sm">
- {{ t("profile.complete_subtitle") || "We need a few more details to process your 3D printing orders." }}
- </p>
- </div>
- <form @submit.prevent="handleSubmit" class="space-y-6">
- <div class="space-y-4">
- <!-- Phone -->
- <div class="space-y-2">
- <label class="text-xs font-semibold uppercase tracking-wider text-muted-foreground ml-1">
- {{ t("upload.phone") }}
- </label>
- <div class="relative group">
- <div class="absolute inset-y-0 left-0 pl-4 flex items-center pointer-events-none text-muted-foreground group-focus-within:text-primary transition-colors">
- <Phone class="w-4 h-4" />
- </div>
- <input
- v-model="formData.phone"
- type="tel"
- required
- placeholder="+381 60 123 4567"
- class="w-full bg-background/50 border border-border/50 rounded-xl pl-11 pr-4 py-3 focus:outline-none focus:ring-2 focus:ring-primary/20 transition-all text-sm"
- />
- </div>
- </div>
- <!-- Shipping Address -->
- <div class="space-y-2">
- <label class="text-xs font-semibold uppercase tracking-wider text-muted-foreground ml-1">
- {{ t("upload.shippingAddress") }}
- </label>
- <div class="relative group">
- <div class="absolute top-3 left-4 text-muted-foreground group-focus-within:text-primary transition-colors">
- <MapPin class="w-4 h-4" />
- </div>
- <textarea
- v-model="formData.shipping_address"
- required
- rows="3"
- placeholder="Street name, Number, City, Postal Code"
- class="w-full bg-background/50 border border-border/50 rounded-xl pl-11 pr-4 py-3 focus:outline-none focus:ring-2 focus:ring-primary/20 transition-all text-sm resize-none"
- />
- </div>
- </div>
- </div>
- <Button type="submit" variant="hero" class="w-full" :disabled="isLoading">
- <Loader2 v-if="isLoading" class="w-5 h-5 animate-spin" />
- <template v-else>
- {{ t("common.save_continue") || "Save & Continue" }}
- <ArrowRight class="w-4 h-4 ml-2" />
- </template>
- </Button>
- </form>
- </div>
- </div>
- </div>
- </Transition>
- </Teleport>
- </template>
- <script setup lang="ts">
- import { ref, reactive } from "vue";
- import { useI18n } from "vue-i18n";
- import { toast } from "vue-sonner";
- import { Phone, MapPin, Loader2, ArrowRight } from "lucide-vue-next";
- import Button from "./ui/button.vue";
- import { updateProfile } from "@/lib/api";
- const props = defineProps<{ isOpen: boolean; user: any }>();
- const emit = defineEmits<{ complete: [] }>();
- const { t } = useI18n();
- const isLoading = ref(false);
- const formData = reactive({
- phone: props.user?.phone ?? "",
- shipping_address: props.user?.shipping_address ?? "",
- });
- async function handleSubmit() {
- if (!formData.phone || !formData.shipping_address) {
- toast.error(t("errors.missing_fields") || "Please fill all fields");
- return;
- }
- isLoading.value = true;
- try {
- await updateProfile(formData);
- toast.success(t("profile.updated_success") || "Profile completed successfully!");
- emit("complete");
- } catch (err: any) {
- toast.error(err.message);
- } finally {
- isLoading.value = false;
- }
- }
- </script>
|