From 52723b200abb84646b5c07fc02bf06773a1e296c Mon Sep 17 00:00:00 2001 From: Legrems Date: Wed, 29 Oct 2025 02:57:10 +0100 Subject: [PATCH] use api in front --- .gitignore | 1 + opus_submitter/opus_submitter/settings.py | 23 -- opus_submitter/src/App.vue | 132 +++++--- opus_submitter/src/components/AdminPanel.vue | 268 +++++++++++++++ opus_submitter/src/components/FileUpload.vue | 11 +- opus_submitter/src/components/PuzzleCard.vue | 19 +- .../src/components/SubmissionForm.vue | 34 +- opus_submitter/src/services/apiService.ts | 314 ++++++++++++++++++ opus_submitter/src/services/ocrService.ts | 98 ++++-- opus_submitter/src/types/index.ts | 32 +- opus_submitter/submissions/api.py | 3 + .../migrations/0005_alter_submission_notes.py | 18 + opus_submitter/submissions/models.py | 208 +++++------- pyproject.toml | 2 - 14 files changed, 900 insertions(+), 263 deletions(-) create mode 100644 opus_submitter/src/components/AdminPanel.vue create mode 100644 opus_submitter/src/services/apiService.ts create mode 100644 opus_submitter/submissions/migrations/0005_alter_submission_notes.py diff --git a/.gitignore b/.gitignore index 4a02eb7..e22f5ad 100644 --- a/.gitignore +++ b/.gitignore @@ -176,3 +176,4 @@ pyrightconfig.json # End of https://www.toptal.com/developers/gitignore/api/python tags +media/ diff --git a/opus_submitter/opus_submitter/settings.py b/opus_submitter/opus_submitter/settings.py index 8426990..bced24b 100644 --- a/opus_submitter/opus_submitter/settings.py +++ b/opus_submitter/opus_submitter/settings.py @@ -39,7 +39,6 @@ INSTALLED_APPS = [ "django.contrib.messages", "django.contrib.staticfiles", "django_vite", - "storages", "accounts", "submissions", ] @@ -140,28 +139,6 @@ STEAM_API_KEY = os.environ.get('STEAM_API_KEY', None) # Set via environment var MEDIA_URL = '/media/' MEDIA_ROOT = BASE_DIR / 'media' -# AWS S3 Configuration -USE_S3 = os.environ.get('USE_S3', 'False').lower() == 'true' - -if USE_S3: - # AWS S3 settings - AWS_ACCESS_KEY_ID = os.environ.get('AWS_ACCESS_KEY_ID') - AWS_SECRET_ACCESS_KEY = os.environ.get('AWS_SECRET_ACCESS_KEY') - AWS_STORAGE_BUCKET_NAME = os.environ.get('AWS_STORAGE_BUCKET_NAME') - AWS_S3_REGION_NAME = os.environ.get('AWS_S3_REGION_NAME', 'us-east-1') - AWS_S3_CUSTOM_DOMAIN = f'{AWS_STORAGE_BUCKET_NAME}.s3.amazonaws.com' - AWS_DEFAULT_ACL = None - AWS_S3_OBJECT_PARAMETERS = { - 'CacheControl': 'max-age=86400', - } - - # S3 Static and Media settings - DEFAULT_FILE_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage' - STATICFILES_STORAGE = 'storages.backends.s3boto3.S3StaticStorage' - - # Override media URL to use S3 - MEDIA_URL = f'https://{AWS_S3_CUSTOM_DOMAIN}/media/' - # File Upload Limits FILE_UPLOAD_MAX_MEMORY_SIZE = 10 * 1024 * 1024 # 10MB DATA_UPLOAD_MAX_MEMORY_SIZE = 10 * 1024 * 1024 # 10MB diff --git a/opus_submitter/src/App.vue b/opus_submitter/src/App.vue index f33e4d9..e2ed0ab 100644 --- a/opus_submitter/src/App.vue +++ b/opus_submitter/src/App.vue @@ -2,14 +2,16 @@ import { ref, onMounted, computed } from 'vue' import PuzzleCard from './components/PuzzleCard.vue' import SubmissionForm from './components/SubmissionForm.vue' +import { puzzleHelpers, submissionHelpers, errorHelpers } from './services/apiService' import type { SteamCollection, SteamCollectionItem, Submission, PuzzleResponse } from './types' -// Mock data - replace with actual API calls later +// API data const collections = ref([]) const puzzles = ref([]) const submissions = ref([]) const isLoading = ref(true) const showSubmissionModal = ref(false) +const error = ref('') // Mock data for development const mockCollections: SteamCollection[] = [ @@ -105,31 +107,83 @@ const responsesByPuzzle = computed(() => { }) onMounted(async () => { - // Simulate API loading - await new Promise(resolve => setTimeout(resolve, 500)) - - collections.value = mockCollections - puzzles.value = mockPuzzles - isLoading.value = false + try { + isLoading.value = true + error.value = '' + + // Load puzzles from API + const loadedPuzzles = await puzzleHelpers.loadPuzzles() + puzzles.value = loadedPuzzles + + // Create mock collection from loaded puzzles for display + if (loadedPuzzles.length > 0) { + collections.value = [{ + id: 1, + steam_id: '3479142989', + title: 'PolyLAN 41', + description: 'Puzzle collection for PolyLAN 41 fil rouge', + author_name: 'Flame Legrems', + total_items: loadedPuzzles.length, + unique_visitors: 31, + current_favorites: 1, + created_at: new Date().toISOString(), + updated_at: new Date().toISOString() + }] + } + + // Load existing submissions + const loadedSubmissions = await submissionHelpers.loadSubmissions() + submissions.value = loadedSubmissions + + } catch (err) { + error.value = errorHelpers.getErrorMessage(err) + console.error('Failed to load data:', err) + } finally { + isLoading.value = false + } }) -const handleSubmission = (submission: Submission) => { - console.log('Submission received:', submission) - - // Add submission to the list - submissions.value.push({ - ...submission, - id: Date.now(), // Simple ID generation for demo - created_at: new Date().toISOString(), - updated_at: new Date().toISOString() - }) - - // Show success message - const puzzleNames = submission.responses.map(r => r.puzzle_name).join(', ') - alert(`Solutions submitted for puzzles: ${puzzleNames}`) - - // Close modal - showSubmissionModal.value = false +const handleSubmission = async (submissionData: { + files: any[], + notes?: string +}) => { + try { + isLoading.value = true + error.value = '' + + // Create submission via API + const response = await submissionHelpers.createFromFiles( + submissionData.files, + puzzles.value, + submissionData.notes + ) + + if (response.error) { + error.value = response.error + alert(`Submission failed: ${response.error}`) + return + } + + if (response.data) { + // Add to local submissions list + submissions.value.unshift(response.data) + + // Show success message + const puzzleNames = response.data.responses.map(r => r.puzzle_name).join(', ') + alert(`Solutions submitted successfully for puzzles: ${puzzleNames}`) + + // Close modal + showSubmissionModal.value = false + } + + } catch (err) { + const errorMessage = errorHelpers.getErrorMessage(err) + error.value = errorMessage + alert(`Submission failed: ${errorMessage}`) + console.error('Submission error:', err) + } finally { + isLoading.value = false + } } const openSubmissionModal = () => { @@ -142,22 +196,7 @@ const closeSubmissionModal = () => { // Function to match puzzle name from OCR to actual puzzle const findPuzzleByName = (ocrPuzzleName: string): SteamCollectionItem | null => { - if (!ocrPuzzleName) return null - - // Try exact match first - let match = puzzles.value.find(p => - p.title.toLowerCase() === ocrPuzzleName.toLowerCase() - ) - - if (!match) { - // Try partial match - match = puzzles.value.find(p => - p.title.toLowerCase().includes(ocrPuzzleName.toLowerCase()) || - ocrPuzzleName.toLowerCase().includes(p.title.toLowerCase()) - ) - } - - return match || null + return puzzleHelpers.findPuzzleByName(puzzles.value, ocrPuzzleName) } @@ -181,6 +220,19 @@ const findPuzzleByName = (ocrPuzzleName: string): SteamCollectionItem | null =>

Loading puzzles...

+ + +
+ +
+

Error Loading Data

+
{{ error }}
+
+ +
diff --git a/opus_submitter/src/components/AdminPanel.vue b/opus_submitter/src/components/AdminPanel.vue new file mode 100644 index 0000000..cdb031f --- /dev/null +++ b/opus_submitter/src/components/AdminPanel.vue @@ -0,0 +1,268 @@ + + + diff --git a/opus_submitter/src/components/FileUpload.vue b/opus_submitter/src/components/FileUpload.vue index 3c9c15a..77bcd10 100644 --- a/opus_submitter/src/components/FileUpload.vue +++ b/opus_submitter/src/components/FileUpload.vue @@ -143,10 +143,11 @@