Fixed Errors
This commit is contained in:
@@ -61,7 +61,17 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="generators-grid" :class="`grid-${generators.length}`">
|
<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>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -73,6 +83,20 @@ import NameGeneratorCard from "./NameGeneratorCard.vue";
|
|||||||
const generators = ref([1, 2, 3, 4]);
|
const generators = ref([1, 2, 3, 4]);
|
||||||
let nextId = 5;
|
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() {
|
function addGenerator() {
|
||||||
if (generators.value.length < 6) {
|
if (generators.value.length < 6) {
|
||||||
generators.value.push(nextId++);
|
generators.value.push(nextId++);
|
||||||
@@ -215,4 +239,42 @@ function removeGenerator() {
|
|||||||
justify-content: center;
|
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>
|
</style>
|
||||||
|
|||||||
@@ -129,11 +129,6 @@
|
|||||||
</svg>
|
</svg>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<!-- Toast notification -->
|
|
||||||
<div v-if="showToast" class="toast">
|
|
||||||
{{ toastMessage }}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -147,6 +142,8 @@ const props = defineProps({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const emit = defineEmits(['show-toast']);
|
||||||
|
|
||||||
const modern = ref(false);
|
const modern = ref(false);
|
||||||
const isLoading = ref(false);
|
const isLoading = ref(false);
|
||||||
|
|
||||||
@@ -208,8 +205,6 @@ const race = ref(races[0].value);
|
|||||||
const language = ref("english");
|
const language = ref("english");
|
||||||
const gender = ref("male");
|
const gender = ref("male");
|
||||||
const fullNames = ref([]);
|
const fullNames = ref([]);
|
||||||
const showToast = ref(false);
|
|
||||||
const toastMessage = ref("");
|
|
||||||
|
|
||||||
function resetGenerator() {
|
function resetGenerator() {
|
||||||
modern.value = false;
|
modern.value = false;
|
||||||
@@ -217,7 +212,6 @@ function resetGenerator() {
|
|||||||
language.value = "english";
|
language.value = "english";
|
||||||
gender.value = "male";
|
gender.value = "male";
|
||||||
fullNames.value = [];
|
fullNames.value = [];
|
||||||
showToast.value = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function generate() {
|
async function generate() {
|
||||||
@@ -227,7 +221,7 @@ async function generate() {
|
|||||||
try {
|
try {
|
||||||
if (modern.value) {
|
if (modern.value) {
|
||||||
// Use API for modern names
|
// 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);
|
const response = await fetch(url);
|
||||||
|
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
@@ -236,18 +230,21 @@ async function generate() {
|
|||||||
|
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
|
|
||||||
if (data.success && data.names) {
|
if (data.names) {
|
||||||
fullNames.value = data.names;
|
fullNames.value = data.names;
|
||||||
} else {
|
} else {
|
||||||
console.error(
|
console.error(
|
||||||
"Failed to fetch modern names:",
|
"Failed to fetch modern names:",
|
||||||
data.message || "Unknown error"
|
data.message || "Unknown error"
|
||||||
);
|
);
|
||||||
fullNames.value = ["Error generating names"];
|
emit('show-toast', {
|
||||||
|
message: `Error: ${data.message || "Failed to generate modern names"}`,
|
||||||
|
type: 'error'
|
||||||
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Use API for fantasy names
|
// 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);
|
const response = await fetch(url);
|
||||||
|
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
@@ -256,19 +253,25 @@ async function generate() {
|
|||||||
|
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
|
|
||||||
if (data.success && data.names) {
|
if (data.names) {
|
||||||
fullNames.value = data.names;
|
fullNames.value = data.names;
|
||||||
} else {
|
} else {
|
||||||
console.error(
|
console.error(
|
||||||
"Failed to fetch fantasy names:",
|
"Failed to fetch fantasy names:",
|
||||||
data.message || "Unknown error"
|
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) {
|
} catch (error) {
|
||||||
console.error("Error fetching names:", error);
|
console.error("Error fetching names:", error);
|
||||||
fullNames.value = [`Error: ${error.message}`];
|
emit('show-toast', {
|
||||||
|
message: `Connection error: ${error.message}`,
|
||||||
|
type: 'error'
|
||||||
|
});
|
||||||
} finally {
|
} finally {
|
||||||
isLoading.value = false;
|
isLoading.value = false;
|
||||||
}
|
}
|
||||||
@@ -277,7 +280,10 @@ async function generate() {
|
|||||||
async function copyToClipboard(name) {
|
async function copyToClipboard(name) {
|
||||||
try {
|
try {
|
||||||
await navigator.clipboard.writeText(name);
|
await navigator.clipboard.writeText(name);
|
||||||
showToastMessage(`"${name}" copied to clipboard!`);
|
emit('show-toast', {
|
||||||
|
message: `"${name}" copied to clipboard!`,
|
||||||
|
type: 'success'
|
||||||
|
});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error("Failed to copy to clipboard:", err);
|
console.error("Failed to copy to clipboard:", err);
|
||||||
// Fallback for older browsers
|
// Fallback for older browsers
|
||||||
@@ -287,17 +293,12 @@ async function copyToClipboard(name) {
|
|||||||
textArea.select();
|
textArea.select();
|
||||||
document.execCommand("copy");
|
document.execCommand("copy");
|
||||||
document.body.removeChild(textArea);
|
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>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
@@ -490,21 +491,6 @@ select:focus {
|
|||||||
opacity: 1;
|
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 {
|
@keyframes slideUp {
|
||||||
from {
|
from {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
|
|||||||
Reference in New Issue
Block a user