Fixed Errors
This commit is contained in:
@@ -61,7 +61,17 @@
|
||||
</div>
|
||||
|
||||
<div class="generators-grid" :class="`grid-${generators.length}`">
|
||||
<NameGeneratorCard v-for="id in generators" :key="id" :card-id="id" />
|
||||
<NameGeneratorCard
|
||||
v-for="id in generators"
|
||||
:key="id"
|
||||
:card-id="id"
|
||||
@show-toast="handleToast"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- Page-level toast notification -->
|
||||
<div v-if="showToast" class="page-toast" :class="`toast-${toastType}`">
|
||||
{{ toastMessage }}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -73,6 +83,20 @@ import NameGeneratorCard from "./NameGeneratorCard.vue";
|
||||
const generators = ref([1, 2, 3, 4]);
|
||||
let nextId = 5;
|
||||
|
||||
// Toast state
|
||||
const showToast = ref(false);
|
||||
const toastMessage = ref("");
|
||||
const toastType = ref("success");
|
||||
|
||||
function handleToast(event) {
|
||||
toastMessage.value = event.message;
|
||||
toastType.value = event.type;
|
||||
showToast.value = true;
|
||||
setTimeout(() => {
|
||||
showToast.value = false;
|
||||
}, event.type === "error" ? 4000 : 2000);
|
||||
}
|
||||
|
||||
function addGenerator() {
|
||||
if (generators.value.length < 6) {
|
||||
generators.value.push(nextId++);
|
||||
@@ -215,4 +239,42 @@ function removeGenerator() {
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
|
||||
/* Page-level toast */
|
||||
.page-toast {
|
||||
position: fixed;
|
||||
top: var(--spacing-lg);
|
||||
right: var(--spacing-lg);
|
||||
padding: var(--spacing-sm) var(--spacing-md);
|
||||
border-radius: var(--border-radius);
|
||||
font-size: 0.9rem;
|
||||
font-weight: 600;
|
||||
z-index: 1000;
|
||||
animation: slideInRight 0.3s ease;
|
||||
max-width: 400px;
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
.toast-success {
|
||||
background: #10b981;
|
||||
color: white;
|
||||
border: 1px solid #059669;
|
||||
}
|
||||
|
||||
.toast-error {
|
||||
background: #ef4444;
|
||||
color: white;
|
||||
border: 1px solid #dc2626;
|
||||
}
|
||||
|
||||
@keyframes slideInRight {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateX(100px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateX(0);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -129,11 +129,6 @@
|
||||
</svg>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<!-- Toast notification -->
|
||||
<div v-if="showToast" class="toast">
|
||||
{{ toastMessage }}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -147,6 +142,8 @@ const props = defineProps({
|
||||
},
|
||||
});
|
||||
|
||||
const emit = defineEmits(['show-toast']);
|
||||
|
||||
const modern = ref(false);
|
||||
const isLoading = ref(false);
|
||||
|
||||
@@ -208,8 +205,6 @@ const race = ref(races[0].value);
|
||||
const language = ref("english");
|
||||
const gender = ref("male");
|
||||
const fullNames = ref([]);
|
||||
const showToast = ref(false);
|
||||
const toastMessage = ref("");
|
||||
|
||||
function resetGenerator() {
|
||||
modern.value = false;
|
||||
@@ -217,7 +212,6 @@ function resetGenerator() {
|
||||
language.value = "english";
|
||||
gender.value = "male";
|
||||
fullNames.value = [];
|
||||
showToast.value = false;
|
||||
}
|
||||
|
||||
async function generate() {
|
||||
@@ -227,7 +221,7 @@ async function generate() {
|
||||
try {
|
||||
if (modern.value) {
|
||||
// Use API for modern names
|
||||
const url = `https://namegen.fernandovideira.com/v1/modern/${language.value}?gender=${gender.value}`;
|
||||
const url = `http://localhost:8080/v1/modern/${language.value}?gender=${gender.value}`;
|
||||
const response = await fetch(url);
|
||||
|
||||
if (!response.ok) {
|
||||
@@ -236,18 +230,21 @@ async function generate() {
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
if (data.success && data.names) {
|
||||
if (data.names) {
|
||||
fullNames.value = data.names;
|
||||
} else {
|
||||
console.error(
|
||||
"Failed to fetch modern names:",
|
||||
data.message || "Unknown error"
|
||||
);
|
||||
fullNames.value = ["Error generating names"];
|
||||
emit('show-toast', {
|
||||
message: `Error: ${data.message || "Failed to generate modern names"}`,
|
||||
type: 'error'
|
||||
});
|
||||
}
|
||||
} else {
|
||||
// Use API for fantasy names
|
||||
const url = `https://namegen.fernandovideira.com/v1/fantasy/${race.value}-names?gender=${gender.value}`;
|
||||
const url = `http://localhost:8080/v1/fantasy/${race.value}-names?gender=${gender.value}`;
|
||||
const response = await fetch(url);
|
||||
|
||||
if (!response.ok) {
|
||||
@@ -256,19 +253,25 @@ async function generate() {
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
if (data.success && data.names) {
|
||||
if (data.names) {
|
||||
fullNames.value = data.names;
|
||||
} else {
|
||||
console.error(
|
||||
"Failed to fetch fantasy names:",
|
||||
data.message || "Unknown error"
|
||||
);
|
||||
fullNames.value = ["Error generating names"];
|
||||
emit('show-toast', {
|
||||
message: `Error: ${data.message || "Failed to generate fantasy names"}`,
|
||||
type: 'error'
|
||||
});
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error fetching names:", error);
|
||||
fullNames.value = [`Error: ${error.message}`];
|
||||
emit('show-toast', {
|
||||
message: `Connection error: ${error.message}`,
|
||||
type: 'error'
|
||||
});
|
||||
} finally {
|
||||
isLoading.value = false;
|
||||
}
|
||||
@@ -277,7 +280,10 @@ async function generate() {
|
||||
async function copyToClipboard(name) {
|
||||
try {
|
||||
await navigator.clipboard.writeText(name);
|
||||
showToastMessage(`"${name}" copied to clipboard!`);
|
||||
emit('show-toast', {
|
||||
message: `"${name}" copied to clipboard!`,
|
||||
type: 'success'
|
||||
});
|
||||
} catch (err) {
|
||||
console.error("Failed to copy to clipboard:", err);
|
||||
// Fallback for older browsers
|
||||
@@ -287,17 +293,12 @@ async function copyToClipboard(name) {
|
||||
textArea.select();
|
||||
document.execCommand("copy");
|
||||
document.body.removeChild(textArea);
|
||||
showToastMessage(`"${name}" copied to clipboard!`);
|
||||
emit('show-toast', {
|
||||
message: `"${name}" copied to clipboard!`,
|
||||
type: 'success'
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function showToastMessage(message) {
|
||||
toastMessage.value = message;
|
||||
showToast.value = true;
|
||||
setTimeout(() => {
|
||||
showToast.value = false;
|
||||
}, 2000);
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
@@ -490,21 +491,6 @@ select:focus {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.toast {
|
||||
position: absolute;
|
||||
bottom: var(--spacing-sm);
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
background: var(--success);
|
||||
color: var(--success-text);
|
||||
padding: var(--spacing-xs) var(--spacing-sm);
|
||||
border-radius: var(--border-radius);
|
||||
font-size: 0.8rem;
|
||||
font-weight: 500;
|
||||
z-index: 10;
|
||||
animation: slideUp 0.3s ease;
|
||||
}
|
||||
|
||||
@keyframes slideUp {
|
||||
from {
|
||||
opacity: 0;
|
||||
|
||||
Reference in New Issue
Block a user