-
Couldn't load subscription status.
- Fork 0
[Feature] [Fest] Quest-1-2-3-x #52
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Changes from 15 commits
Commits
Show all changes
18 commits
Select commit
Hold shift + click to select a range
2fc45d7
feat: complete quest-1-2-3-x
Riodsa 9980c97
add : test fest 2 data
neennera 5bc490c
fox : show image
neennera c1a9913
refactor : move shop into new file
neennera 3694dc1
add : other page title & button list
neennera 33d690a
feat: add images banner for quest-3-x
Riodsa 5f1d70c
Merge remote-tracking branch 'origin/feat/feat/quest2-sub-shop' into …
Riodsa b67e73c
fix: change date of quest-3-4
Riodsa 7395284
feat: add link for LineOA, change ggForm Link for each quests
Riodsa 49a73f0
fix: update fest2
neennera 65a573e
chore : remove unused file
neennera 4e3802f
Merge branch 'dev' into feat/fest/quest-1,2,3-x
Riodsa 1af6238
Merge branch 'dev' into feat/fest/quest-1,2,3-x
Taihenc 3f3d379
Merge branch 'dev' into feat/fest/quest-1,2,3-x
MasterIceZ bd34e42
Merge branch 'dev' into feat/fest/quest-1,2,3-x
Taihenc 3dae685
revert: pnpm-lock
Taihenc 29d5c0d
chore: fix linting
Taihenc f829261
Merge branch 'dev' into feat/fest/quest-1,2,3-x
Taihenc File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,110 @@ | ||
| import fs from 'fs'; | ||
| import path from 'path'; | ||
|
|
||
| // Read CSV file with UTF-8 encoding | ||
| const csvPath = path.join(process.cwd(), 'public', 'fest', 'fest_quest2_shop_list_4.csv'); | ||
| const csvContent = fs.readFileSync(csvPath, 'utf-8'); | ||
|
|
||
| // Parse CSV content with proper handling of quoted fields | ||
| function parseCSV(content: string) { | ||
| // Handle different line endings (Windows \r\n, Unix \n, Mac \r) | ||
| const lines = content.replace(/\r\n/g, '\n').replace(/\r/g, '\n').split('\n'); | ||
|
|
||
| if (lines.length === 0) return []; | ||
|
|
||
| // Parse headers | ||
| const headers = parseCSVLine(lines[0]); | ||
| const shops = []; | ||
|
|
||
| for (let i = 1; i < lines.length; i++) { | ||
| const line = lines[i].trim(); | ||
| if (!line) continue; | ||
|
|
||
| const values = parseCSVLine(line); | ||
|
|
||
| if (values.length >= 3) { // At least have number, name, zone | ||
| const shop: any = {}; | ||
| headers.forEach((header, index) => { | ||
| const value = values[index] || ''; | ||
| shop[header.trim()] = value.trim(); | ||
| if(header === 'image'){ | ||
| shop[header] = convertGoogleDriveUrl(value.trim()) | ||
| } | ||
| }); | ||
|
|
||
| // Only add shops that have a name and zone | ||
| if (shop.name && shop.zone) { | ||
| shops.push(shop); | ||
| } | ||
| } | ||
| } | ||
| return shops; | ||
| } | ||
|
|
||
| // Helper function to parse a single CSV line handling quoted fields | ||
| function parseCSVLine(line: string): string[] { | ||
| const result = []; | ||
| let current = ''; | ||
| let inQuotes = false; | ||
| let i = 0; | ||
|
|
||
| while (i < line.length) { | ||
| const char = line[i]; | ||
|
|
||
| if (char === '"') { | ||
| if (inQuotes && line[i + 1] === '"') { | ||
| // Handle escaped quotes inside quoted field | ||
| current += '"'; | ||
| i += 2; | ||
| continue; | ||
| } else { | ||
| // Toggle quote state | ||
| inQuotes = !inQuotes; | ||
| } | ||
| } else if (char === ',' && !inQuotes) { | ||
| // End of field | ||
| result.push(current); | ||
| current = ''; | ||
| } else { | ||
| current += char; | ||
| } | ||
| i++; | ||
| } | ||
|
|
||
| // Push the last field | ||
| result.push(current); | ||
|
|
||
| return result; | ||
| } | ||
|
|
||
|
|
||
| // Helper function to convert Google Drive share links to direct image URLs | ||
| function convertGoogleDriveUrl(url: string): string { | ||
| console.log('Original URL:', url); | ||
|
|
||
| if (!url) return ''; | ||
|
|
||
| // Match Google Drive URLs and extract file ID | ||
| const driveRegex = /(?:drive\.google\.com\/(?:file\/d\/|open\?id=))([a-zA-Z0-9_-]+)/; | ||
| const match = url.match(driveRegex); | ||
|
|
||
| if (match && match[1]) { | ||
| // Try multiple formats for better compatibility | ||
| const fileId = match[1]; | ||
|
|
||
| // Format 1: Standard thumbnail (works best for public images) | ||
| const directUrl = `https://drive.google.com/thumbnail?id=${fileId}&sz=w400`; | ||
|
|
||
| console.log('Converted URL:', directUrl); | ||
| return directUrl; | ||
| } | ||
|
|
||
| console.log('Not a Google Drive URL, returning original:', url); | ||
| return url; // Return original URL if it's not a Google Drive URL | ||
| } | ||
|
|
||
| const allShops = parseCSV(csvContent); | ||
| export const zoneAShops = allShops.filter(shop => shop.zone === 'A'); | ||
| export const zoneBShops = allShops.filter(shop => shop.zone === 'B'); | ||
| export const zoneCShops = allShops.filter(shop => shop.zone === 'C'); | ||
| export const zoneDShops = allShops.filter(shop => shop.zone === 'D'); |
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,97 @@ | ||
| --- | ||
| import Layout from "@/layouts/fest/FestWithNavbar.astro"; | ||
| import HorizonlineFest from "@/components/common/HorizonlineFest.astro"; | ||
| import ButtonFest from "@/components/common/ButtonFest.astro"; | ||
| import {zoneAShops} from "@/components/fest/quest2_csv_reader" | ||
| --- | ||
|
|
||
| <Layout> | ||
| <div class="flex flex-col space-y-2 px-4 py-6"> | ||
| <div | ||
| class="sticky top-0 z-10 flex w-full justify-between px-3 py-2 backdrop-blur-md" | ||
| > | ||
| <a href="/fest/quest-2" class="mt-2.5 text-2xl font-bold">{"<"}</a> | ||
| <div class="flex flex-col gap-1 text-center"> | ||
| <p class="font-family-orbitron text-5xl">Quest 2 - A</p> | ||
| <p class="text-2xl font-extralight">ร้านค้าโซน A</p> | ||
| </div> | ||
| <a href="/fest/quest-2-B" class="mt-2.5 text-2xl font-bold">{">"}</a> | ||
| </div> | ||
|
|
||
| <div class="space-y-6 pt-4"> | ||
| {zoneAShops.map((shop, index) => ( | ||
| <div class="shop-item"> | ||
| {index > 0 && <HorizonlineFest variant="blue" />} | ||
|
|
||
| <div class="space-y-4"> | ||
| {/* Shop Name */} | ||
| <h2 class="text-2xl font-bold text-center text-pink-500"> | ||
| {shop.name} | ||
| </h2> | ||
|
|
||
| {/* Shop Image */} | ||
| {shop.image && ( | ||
| <div class="flex justify-center"> | ||
| <img | ||
| src={shop.image} | ||
| alt={shop.name} | ||
| class="max-w-full h-48 object-cover rounded-lg shadow-md" | ||
| loading="lazy" | ||
| onerror="console.log('Image failed to load:', this.src); this.style.display='none';" | ||
| onload="console.log('Image loaded successfully:', this.src);" | ||
| /> | ||
| </div> | ||
| )} | ||
|
|
||
| <div class="p-4"> | ||
| <h3 class="font-semibold text-lg text-pink-400 mb-2">เมนูแนะนำ:</h3> | ||
| <p | ||
| class="text-justify leading-relaxed hyphens-auto text-white" | ||
| lang="th" | ||
| style="text-align: justify; text-align-last: left; word-spacing: 0.1em;" | ||
| > | ||
| {shop.manu} | ||
| </p> | ||
| </div> | ||
| <div class="p-4"> | ||
| <h3 class="font-semibold text-lg text-pink-400 mb-2">รายละเอียด:</h3> | ||
| <p | ||
| class="text-justify leading-relaxed hyphens-auto text-white" | ||
| lang="th" | ||
| style="text-align: justify; text-align-last: left; word-spacing: 0.1em;" | ||
| > | ||
| {shop.description} | ||
| </p> | ||
| </div> | ||
| <div class="p-4"> | ||
| <h3 class="font-semibold text-lg text-pink-400 mb-2">เวลาเปิด-ปิด:</h3> | ||
| <p | ||
| class="text-justify leading-relaxed hyphens-auto text-white" | ||
| lang="th" | ||
| style="text-align: justify; text-align-last: left; word-spacing: 0.1em;" | ||
| > | ||
| {shop.time} | ||
| </p> | ||
| </div> | ||
|
|
||
|
|
||
| {/* Google Maps Button */} | ||
| {shop.maps && ( | ||
| <div class="flex justify-center pt-2"> | ||
| <ButtonFest | ||
| color="pink" | ||
| size="big" | ||
| href={shop.maps} | ||
| target="_blank" | ||
| rel="noopener noreferrer" | ||
| > | ||
| Google Maps | ||
| </ButtonFest> | ||
| </div> | ||
| )} | ||
| </div> | ||
| </div> | ||
| ))} | ||
| </div> | ||
| </div> | ||
| </Layout> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,97 @@ | ||
| --- | ||
| import Layout from "@/layouts/fest/FestWithNavbar.astro"; | ||
| import HorizonlineFest from "@/components/common/HorizonlineFest.astro"; | ||
| import ButtonFest from "@/components/common/ButtonFest.astro"; | ||
| import {zoneBShops} from "@/components/fest/quest2_csv_reader" | ||
| --- | ||
|
|
||
| <Layout> | ||
| <div class="flex flex-col space-y-2 px-4 py-6"> | ||
| <div | ||
| class="sticky top-0 z-10 flex w-full justify-between px-3 py-2 backdrop-blur-md" | ||
| > | ||
| <a href="/fest/quest-2-A" class="mt-2.5 text-2xl font-bold">{"<"}</a> | ||
| <div class="flex flex-col gap-1 text-center"> | ||
| <p class="font-family-orbitron text-5xl">Quest 2 - B</p> | ||
| <p class="text-2xl font-extralight">ร้านค้าโซน B</p> | ||
| </div> | ||
| <a href="/fest/quest-2-C" class="mt-2.5 text-2xl font-bold">{">"}</a> | ||
| </div> | ||
|
|
||
| <div class="space-y-6 pt-4"> | ||
| {zoneBShops.map((shop, index) => ( | ||
| <div class="shop-item"> | ||
| {index > 0 && <HorizonlineFest variant="blue" />} | ||
|
|
||
| <div class="space-y-4"> | ||
| {/* Shop Name */} | ||
| <h2 class="text-2xl font-bold text-center text-pink-500"> | ||
| {shop.name} | ||
| </h2> | ||
|
|
||
| {/* Shop Image */} | ||
| {shop.image && ( | ||
| <div class="flex justify-center"> | ||
| <img | ||
| src={shop.image} | ||
| alt={shop.name} | ||
| class="max-w-full h-48 object-cover rounded-lg shadow-md" | ||
| loading="lazy" | ||
| onerror="console.log('Image failed to load:', this.src); this.style.display='none';" | ||
| onload="console.log('Image loaded successfully:', this.src);" | ||
| /> | ||
| </div> | ||
| )} | ||
|
|
||
| <div class="p-4"> | ||
| <h3 class="font-semibold text-lg text-pink-400 mb-2">เมนูแนะนำ:</h3> | ||
| <p | ||
| class="text-justify leading-relaxed hyphens-auto text-white" | ||
| lang="th" | ||
| style="text-align: justify; text-align-last: left; word-spacing: 0.1em;" | ||
| > | ||
| {shop.manu} | ||
| </p> | ||
| </div> | ||
| <div class="p-4"> | ||
| <h3 class="font-semibold text-lg text-pink-400 mb-2">รายละเอียด:</h3> | ||
| <p | ||
| class="text-justify leading-relaxed hyphens-auto text-white" | ||
| lang="th" | ||
| style="text-align: justify; text-align-last: left; word-spacing: 0.1em;" | ||
| > | ||
| {shop.description} | ||
| </p> | ||
| </div> | ||
| <div class="p-4"> | ||
| <h3 class="font-semibold text-lg text-pink-400 mb-2">เวลาเปิด-ปิด:</h3> | ||
| <p | ||
| class="text-justify leading-relaxed hyphens-auto text-white" | ||
| lang="th" | ||
| style="text-align: justify; text-align-last: left; word-spacing: 0.1em;" | ||
| > | ||
| {shop.time} | ||
| </p> | ||
| </div> | ||
|
|
||
|
|
||
| {/* Google Maps Button */} | ||
| {shop.maps && ( | ||
| <div class="flex justify-center pt-2"> | ||
| <ButtonFest | ||
| color="pink" | ||
| size="big" | ||
| href={shop.maps} | ||
| target="_blank" | ||
| rel="noopener noreferrer" | ||
| > | ||
| Google Maps | ||
| </ButtonFest> | ||
| </div> | ||
| )} | ||
| </div> | ||
| </div> | ||
| ))} | ||
| </div> | ||
| </div> | ||
| </Layout> |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.