Skip to content

Commit d69a739

Browse files
committed
Translations, i18n, optimizations, cleanups, you name it - we got it
1 parent 779bd4c commit d69a739

30 files changed

+3851
-767
lines changed

.github/copilot-instructions.md

+291
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,291 @@
1+
# Copilot Instructions
2+
3+
## Project Overview
4+
This project uses:
5+
6+
- **Nuxt (Vue 3 & Nitro)** for frontend and backend.
7+
- **MongoDB (via Mongoose)** for data storage.
8+
- **Redis (via ioredis)** for caching.
9+
- **BullMQ** for job processing.
10+
11+
## Project Structure
12+
13+
- **API:** `/server/api`
14+
- **Nitro Routes:** `/server/routes`
15+
- **Vue Pages:** `/pages`
16+
- **MongoDB Models:** `/server/models`
17+
- **Queues:** `/queue`
18+
- **Cron Jobs:** `/cron`
19+
- **Console Commands:** `/console`
20+
- **i18n Files:** `/i18n/locales`
21+
22+
## Code Conventions
23+
24+
- Use **Biome** for formatting.
25+
- Follow **TypeScript** best practices.
26+
- Use **ESLint** for linting.
27+
- Structure Vue components modularly.
28+
- Use composition API with `<script setup>` syntax.
29+
- Prefer typed refs and reactive objects.
30+
- Use kebab-case for file names and component names.
31+
- Use PascalCase for component imports and registrations.
32+
- Use camelCase for variables, functions, and properties.
33+
- Use UPPER_SNAKE_CASE for constants.
34+
- Include JSDoc comments for public functions and types.
35+
- Organize imports by: built-in modules, external modules, internal modules.
36+
37+
## Common Patterns
38+
39+
### API Calls
40+
```ts
41+
// Use useFetch for API calls with proper typing
42+
const { data, error, pending, refresh } = await useFetch<ApiResponse>('/api/endpoint', {
43+
method: 'POST',
44+
body: payload,
45+
onResponseError: (error) => {
46+
console.error('API error:', error);
47+
// Handle error appropriately
48+
}
49+
});
50+
```
51+
52+
### Error Handling
53+
```ts
54+
try {
55+
// Operation that might fail
56+
const result = await riskyOperation();
57+
return result;
58+
} catch (error) {
59+
console.debug('Error in operation:', error);
60+
throw createError({
61+
statusCode: 500,
62+
statusMessage: 'Operation failed',
63+
data: { context: 'Additional context' }
64+
});
65+
}
66+
```
67+
68+
### MongoDB Model Pattern
69+
```ts
70+
// server/models/example.model.ts
71+
import mongoose from 'mongoose';
72+
import type { Document, Model } from 'mongoose';
73+
74+
export interface IExample extends Document {
75+
name: string;
76+
description?: string;
77+
createdAt: Date;
78+
updatedAt: Date;
79+
}
80+
81+
const schema = new mongoose.Schema(
82+
{
83+
name: { type: String, required: true, index: true },
84+
description: { type: String }
85+
},
86+
{ timestamps: true }
87+
);
88+
89+
// Add any methods here
90+
schema.methods.someMethod = function() {
91+
// Method implementation
92+
};
93+
94+
// Add any statics here
95+
schema.statics.findByName = function(name: string) {
96+
return this.findOne({ name });
97+
};
98+
99+
export const Example: Model<IExample> = mongoose.model<IExample>('Example', schema);
100+
```
101+
102+
## Vue Component Template
103+
```vue
104+
<template>
105+
<div class="component-container">
106+
<h1>{{ $t('component.title') }}</h1>
107+
<div v-if="loading">{{ $t('common.loading') }}</div>
108+
<div v-else-if="error">{{ $t('common.error') }}</div>
109+
<div v-else>
110+
<!-- Component content -->
111+
</div>
112+
</div>
113+
</template>
114+
115+
<script setup lang="ts">
116+
import { ref, computed, onMounted } from 'vue';
117+
import type { PropType } from 'vue';
118+
119+
// Props
120+
const props = defineProps({
121+
id: {
122+
type: String as PropType<string>,
123+
required: true
124+
}
125+
});
126+
127+
// Emits
128+
const emit = defineEmits<{
129+
(e: 'update', value: string): void
130+
}>();
131+
132+
// State
133+
const loading = ref(false);
134+
const error = ref<Error | null>(null);
135+
const data = ref<any>(null);
136+
137+
// Computed
138+
const isDataValid = computed(() => !!data.value && data.value.length > 0);
139+
140+
// Methods
141+
const fetchData = async () => {
142+
loading.value = true;
143+
error.value = null;
144+
145+
try {
146+
const { data: result } = await useFetch(`/api/endpoint/${props.id}`);
147+
data.value = result.value;
148+
} catch (err) {
149+
console.debug('Error fetching data:', err);
150+
error.value = err as Error;
151+
} finally {
152+
loading.value = false;
153+
}
154+
};
155+
156+
// Lifecycle
157+
onMounted(() => {
158+
fetchData();
159+
});
160+
</script>
161+
162+
<style scoped>
163+
.component-container {
164+
/* Component styling */
165+
}
166+
</style>
167+
```
168+
169+
## Example Templates
170+
171+
- **Queue Job**
172+
```js
173+
export default {
174+
name: "queue-name",
175+
description: "Short queue description",
176+
run: () => {
177+
// Queue job implementation
178+
}
179+
};
180+
```
181+
182+
- **Cron Job**
183+
```js
184+
export default {
185+
name: "cron-name",
186+
description: "Short cron description",
187+
schedule: "0 0 * * *",
188+
run: async () => {
189+
// Cron job implementation
190+
},
191+
};
192+
```
193+
194+
- **Console Command**
195+
```js
196+
export default {
197+
name: "command-name",
198+
description: "Short command description",
199+
longRunning: false,
200+
run: async () => {
201+
// Command implementation
202+
return { response: "Command completed" };
203+
},
204+
};
205+
```
206+
207+
- **API Endpoint**
208+
```ts
209+
// server/api/resource/[id].ts
210+
export default defineEventHandler(async (event) => {
211+
try {
212+
const id = getRouterParam(event, 'id');
213+
const query = getQuery(event);
214+
215+
// For POST/PUT/PATCH requests
216+
const body = await readBody(event);
217+
218+
// Implementation
219+
const result = await someOperation(id, query, body);
220+
221+
return result;
222+
} catch (error) {
223+
console.debug('API error:', error);
224+
throw createError({
225+
statusCode: 500,
226+
statusMessage: 'Failed to process request',
227+
data: error
228+
});
229+
}
230+
});
231+
```
232+
233+
- **Composable**
234+
```ts
235+
// composables/useFeature.ts
236+
export function useFeature() {
237+
const state = ref({});
238+
const loading = ref(false);
239+
const error = ref(null);
240+
241+
const fetchData = async () => {
242+
// Implementation
243+
};
244+
245+
const processData = (data) => {
246+
// Implementation
247+
};
248+
249+
return {
250+
state,
251+
loading,
252+
error,
253+
fetchData,
254+
processData
255+
};
256+
}
257+
```
258+
259+
## Testing Strategy
260+
261+
- Use **Vitest** for unit tests
262+
- Use **Cypress** for end-to-end tests
263+
- Place unit tests next to the files they test with `.spec.ts` or `.test.ts` suffix
264+
- Focus on testing business logic and complex operations
265+
- Mock external dependencies when testing components or services
266+
267+
## Internationalization
268+
269+
- Use `$t('key')` for translations in Vue templates
270+
- Use `t('key')` in composables with `useI18n()` hook
271+
- Organize translations by feature area
272+
- Include all user-facing strings in translation files
273+
- Support locale fallbacks
274+
275+
## Copilot-Specific Instructions
276+
277+
- Follow project structure and conventions.
278+
- Use `useFetch` or `useAsyncData` for API calls.
279+
- Handle errors with try-catch blocks.
280+
- Use `console.debug` for logging.
281+
- Avoid exposing sensitive data.
282+
- Implement proper TypeScript typing for all functions and variables.
283+
- Follow the single responsibility principle.
284+
- Utilize existing composables and utilities before creating new ones.
285+
- Always consider internationalization for user-facing strings.
286+
- Include appropriate error handling for async operations.
287+
- Consider performance implications, especially with MongoDB queries.
288+
- Use proper index definitions when querying MongoDB.
289+
- Implement proper caching strategies when appropriate.
290+
- Ensure queue jobs are idempotent when possible.
291+
- Follow RESTful principles for API endpoints.

app.css

+7-2
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,11 @@ body.overflow-hidden {
9393
}
9494

9595
/* Scrollbar styling */
96+
* {
97+
scrollbar-width: thin;
98+
scrollbar-color: var(--color-primary-400) transparent;
99+
}
100+
96101
*::-webkit-scrollbar {
97102
width: 10px;
98103
}
@@ -106,7 +111,7 @@ body.overflow-hidden {
106111
border-radius: 10px;
107112
}
108113

109-
/* Override any inline padding styles */
114+
/* Fix padding issues */
110115
html[style*="padding-right"],
111116
body[style*="padding-right"] {
112117
padding-right: 0 !important;
@@ -119,7 +124,7 @@ body[style*="padding-right"] {
119124
padding-right: 0 !important;
120125
}
121126

122-
/* Custom opacity utility classes using CSS variables */
127+
/* Custom opacity utility classes */
123128
.custom-bg-white-60 {
124129
background-color: rgba(255, 255, 255, 0.6);
125130
}

0 commit comments

Comments
 (0)