Compare commits

...

162 Commits

Author SHA1 Message Date
7bc84cea75 fix: shop catalog always reflects latest data after admin changes
- Add force-dynamic to /api/catalog so Next.js never serves a
  stale cached route response to the shop
- Add invalidateCatalogCache() to catalog-cache lib to drop the
  30s in-process memory cache on demand
- Call invalidateCatalogCache() after every admin PATCH/DELETE on
  an item so override saves are reflected on the very next shop
  request (no 30s delay)

Refresh from Square already updated the shared disk + memory cache;
force-dynamic ensures the shop route handler actually runs each time.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-18 10:12:41 -04:00
27093bcd54 fix: multi-category checkboxes in admin + requires-delivery toggle
- Category selector replaced with checkboxes — items can now be
  assigned to multiple categories directly in admin (not just Square).
  Each category shows a "Square" label if it came from the Square
  assignment. Saves as categoriesOverride[] (array of category names).
- categoriesOverride takes precedence over old categoryOverride in the
  catalog route; old overrides still work as fallback.
- Requires-delivery toggle and custom rate fields were already in the
  code but needed container rebuild to appear — no logic change.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-18 09:44:00 -04:00
0ea1b98a1f feat: required delivery toggle with custom rates per item
Items can now be marked as "requires delivery" in admin — these items
cannot be picked up and must be delivered (and struck).

- Admin item editor: "Requires delivery" checkbox + custom base/per-mile
  rate fields that appear when the toggle is on
- ProductCard: "Delivery & setup required" note on the card
- CartDrawer: pickup toggle is hidden and replaced with an explanation
  when any cart item requires delivery; the quote call passes the
  item's custom rate override (highest base + highest per-mile wins
  when multiple requires-delivery items are in the cart)
- delivery-quote API: accepts optional rateOverride to apply per-item
  pricing on top of the inferred tier

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-18 09:31:29 -04:00
107ef43a0e fix: hide category tab when it's already shown as an occasion tab
If a "Mothers Day" or "Graduation" occasion is active and its
squareCategorySlug matches a product category, suppress the duplicate
regular category tab so it doesn't appear twice in the bar.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-17 15:45:46 -04:00
623b237826 feat: multi-category items and fix new items not appearing
Items can now belong to multiple Square categories and appear in all
matching tabs (e.g. a Mother's Day balloon also shows under Easter).

Also fixes new items not appearing when the Square account has no
"online" category — previously this caused zero items to load; now
it falls back to showing all items.

Changes:
- CatalogItem gains categories[] + categoryLabels[] (multi-category)
- square.ts collects all non-skip categories per item; "online" filter
  is now optional (show all if category doesn't exist in Square)
- catalog/route.ts propagates categoryOverride into categories[0]
- FeaturedProducts: tabs and filter use the full categories array
- Admin CategoryDisplayEditor sees all categories from multi-cat items

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-17 15:39:31 -04:00
84ab6bef2d feat: featured items — admin toggle, badge, sorted to top
- Add featured to ItemOverride so it can be set per-item in admin
- Catalog API applies the override and sorts featured items before
  non-featured (within each group, sortOrder still applies)
- ProductCard shows a teal Featured badge on the image when featured
  and not sold out
- Admin item editor has a  Featured checkbox beside Hidden

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-17 14:21:33 -04:00
6705293e50 fix/feat: hex conflict, scroll-to-top, search all, admin error emails
- Fix Chrome Rose Gold hex (#B76E79 → #C17F87) so it no longer
  conflicts with Classic Rose Gold; image still used for display
- ScrollToTop hides when cart drawer is open and uses z-index 98
  (below the drawer); uses drawerOpen from CartContext
- Search now switches to All tab automatically so results span every
  item, not just the active category
- Add sendAdminErrorAlert() to notify.ts; checkout route emails
  admin@beachpartyballoons.com on unexpected server errors and on
  critical calendar-write failures; card decline errors are not
  forwarded (customers can self-resolve those)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-17 14:19:29 -04:00
01c908e919 fix: color picker selection keyed on name instead of hex
Classic Rose Gold and Chrome Rose Gold share the same hex (#B76E79),
so clicking one would deselect the other. Switched all selection
checks (toggle, remove, highlight) to use color.name which is unique.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-17 14:08:57 -04:00
6865d2d437 fix: lock body scroll when any modal or drawer is open
Add useLockBodyScroll hook (sets overflow:hidden on body, restores on
unmount) and apply it to ColorPicker, AdminColorFilter, WelcomeModal,
and GuidedTour. CartDrawer uses an inline effect keyed on drawerOpen
since it is always mounted.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-16 09:12:07 -04:00
e95ec68931 feat: admin color availability filter per item
- Add disabledColors field to ItemOverride and CatalogItem
- Propagate through catalog API applyOverrides
- ColorPicker filters disabled colors out before showing to customers
- New AdminColorFilter modal: same collapsible family layout and balloon
  swatches as the customer view; click to hide/show individual colors;
  Enable all / Disable all shortcuts; badge shows count of hidden colors
- Button appears in the color limits section for color-enabled items

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-16 09:00:32 -04:00
1861e10d6d fix: restore missing next/server imports + add force-dynamic to admin routes
A botched sed command stripped the first import line from every admin
route file, breaking NextRequest/NextResponse references. Restored all
imports and added export const dynamic = 'force-dynamic' to all admin
GET handlers so Next.js 14 never serves a stale cached response after
a save — this was the root cause of changes appearing not to save.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-16 08:50:34 -04:00
f2fa8e3c17 fix: zoom chrome/metallic preview dots to 220% background-size
Image-based colors (chrome/metallic) have a balloon silhouette against
a transparent bg, so cover was fitting the whole image including
whitespace. 220% zooms into the center where the finish actually is.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-15 14:51:24 -04:00
c22b668bc5 fix: update /color-picker/ → /color/ in estore ColorPicker and CSS
ColorPicker.tsx was constructing image URLs with the old /color-picker/
prefix. globals.css had the same for the balloon-mask.svg SVG mask.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-15 14:47:16 -04:00
0576677523 feat: scroll-to-top button in estore; fix JS/CSS cache headers on main site
- Add ScrollToTop component matching main site's green Top button
  (appears after 130px scroll, same styling and font)
- Fix main-site server.js: JS/CSS now use max-age=3600 + must-revalidate
  instead of 30d immutable — changes reach users within 1 hour instead
  of being stuck in browser cache for a month
- Images/fonts keep 30d immutable (safe, as they are content-addressed)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-15 14:41:42 -04:00
c6d5a0265f fix: tour init on All tab + 11" Latex card; fix modal title truncation
- Tour now switches to the All tab and clears search on start, ensuring
  the 11" Latex product is always visible and the exit overlay works
- data-tour="first-card" now targets the 11" Latex item by name instead
  of whichever card happens to be first in the filtered list
- Modal header title now truncates with ellipsis so the X close button
  is never pushed off screen by a long product name

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-15 14:39:45 -04:00
6fea1f2be1 fix: hide delivery line in order summary when pickup is selected
quote was non-null after entering a delivery address, so the delivery
fee row showed even after switching back to pickup.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-15 14:34:38 -04:00
c130f9bcdf nginx: redirect /color-picker/* to /color/*
Browsers with cached pages from the old /color-picker/ path resolve
relative image URLs against that base, causing 404s after the rename.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-15 14:32:25 -04:00
e2d9ae7541 nginx: redirects for legal pages, gzip, security headers
- 301 redirects /privacy|terms|refund → /shop/* (pages live in estore)
- gzip compression for HTML/CSS/JS/JSON/SVG
- X-Frame-Options, X-Content-Type-Options, Referrer-Policy headers

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-15 13:44:56 -04:00
f4b1f7722e Fix data dir permissions and legal doc links
- Dockerfile: create /app/data owned by nextjs before USER switch so fresh
  deployments work without manual chown. Existing servers need:
    sudo chown -R 1001:1001 estore/data
- nav.js: fix footer legal links to point to /shop/privacy|terms|refund
  (pages live in estore, not main site)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-15 13:28:20 -04:00
215a8f2e3f Add Plausible Analytics to color page and estore
Both were missing tracking. All pages now report to beachpartyballoons.com
in Plausible.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-14 21:25:06 -04:00
50680a323f Major overhaul: shared nav, admin improvements, email enhancements, routing fixes
Navigation & layout
- Replace per-page hardcoded nav/footer with shared nav.js (client-side injection)
- Add nginx reverse proxy back to docker-compose for clean localhost routing
- Rename /color-picker/ to /color/ across nav, directory, and references

eStore admin
- Add variation hiding controls (mirrors existing modifier hiding)
- Add delivery rate editor (base fee + per-mile per tier, persisted to data/)
- Fix all missing BASE prefix on fetch calls (admin PATCH/DELETE, availability, slots, colors)
- Mount estore/data/ as a Docker volume so admin config survives rebuilds

Booking & calendar
- Set pickup calendar events to TRANSPARENT (free) so they don't block delivery slots
- Skip CANCELLED events in busy-time calculation
- Re-check slot availability at checkout before charging (409 on conflict)

Phone & email validation
- Auto-format phone as (XXX) XXX-XXXX as user types
- Require exactly 10 digits; tighten email regex

Confirmation emails (store alert + customer)
- Full item detail per line: name, price, add-ons, colors, note
- Charges breakdown: subtotal, delivery fee, tax, total
- Delivery window: simplified M/D/YY h:mm – h:mm AM/PM format
- .ics calendar attachment on customer confirmation

Delivery rates
- Extract configurable rates to delivery-rates.ts (server-only, no fs in client bundle)
- calcDelivery() accepts optional rates param; delivery-quote route passes configured rates

Content
- Change all "40+ latex colors" references to "70+"

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-14 21:14:06 -04:00
9f9f326af9 Add root docker-compose and osrm data directory 2026-04-13 19:27:07 -04:00
668ee46ba6 Add root .gitignore 2026-04-13 19:22:46 -04:00
c984c14085 Remove terms page — now lives in estore footer 2026-04-13 19:22:36 -04:00
f58ae2c5f7 Add 'main-site/color-picker/' from commit '248d73a619ea4fbdca711a516f464cd0a505bfae'
git-subtree-dir: main-site/color-picker
git-subtree-mainline: 21ebb9667b34023f8d563bf8fa2abf7f838f51d7
git-subtree-split: 248d73a619ea4fbdca711a516f464cd0a505bfae
2026-04-13 19:22:30 -04:00
21ebb9667b Add 'estore/' from commit 'e34dfc397c94025670baa2b73b482c01f3033a6a'
git-subtree-dir: estore
git-subtree-mainline: 746868d720b9be1003a2f783b7a12d526d8eea60
git-subtree-split: e34dfc397c94025670baa2b73b482c01f3033a6a
2026-04-13 19:22:23 -04:00
746868d720 Add 'main-site/' from commit '5cefb4d1618bc54ae0e86830421a8c911900302c'
git-subtree-dir: main-site
git-subtree-mainline: 4d1daa39101c0a85ca6d916f1c31139faf39632a
git-subtree-split: 5cefb4d1618bc54ae0e86830421a8c911900302c
2026-04-13 19:22:17 -04:00
4d1daa3910 Initial monorepo root 2026-04-13 19:21:56 -04:00
248d73a619 Redesign color picker UI and improve palette modals 2026-02-22 15:51:44 -05:00
5cefb4d161 Fix Contact Us button markup 2025-12-27 11:37:07 -05:00
8b0793c42f Enhance FAQ and gallery UI 2025-12-27 11:30:38 -05:00
b585d851dd Add trusted logos and manual reviews 2025-12-27 10:29:38 -05:00
7c42800245 Prevent caching of store status updates 2025-12-26 12:58:46 -05:00
a3b8593133 Improve gallery sharing and admin tagging 2025-12-26 12:50:25 -05:00
3a679eb03c chore: match uploads by stripping timestamp prefixes 2025-12-08 16:02:51 -05:00
cf575afc3f chore: normalize brace suffix in reprocess base names 2025-12-08 15:59:34 -05:00
a94d938131 chore: allow reprocess to use raw source files 2025-12-08 15:56:12 -05:00
d230e88bd1 chore: log missing sources during reprocess 2025-12-08 15:52:39 -05:00
467fcbffb7 chore: ignore uploads and add reprocess script 2025-12-08 15:40:40 -05:00
5c391f3dee fix: load gallery/admin scripts from local folders 2025-12-08 14:17:25 -05:00
7e06f7f63a fix: serve bundle from /build path 2025-12-08 13:58:30 -05:00
35956d2849 fix: correct gallery asset paths and update fetch URL 2025-12-08 13:49:21 -05:00
7b3cfb5178 chore: ignore mongodb_data 2025-12-08 13:37:25 -05:00
9ca29e13de chore: update gallery tooling and docker setup 2025-12-08 13:26:36 -05:00
a58b0f7cdb update colors 2025-12-08 09:34:26 -05:00
c340cd2eaf Reorganize gallery, optimize builds, add backups 2025-11-25 16:22:29 -05:00
b2a3e5d605 fix: Add HEIC/HEIF support and resolve CORS issues
- Add libheif-dev to backend Dockerfile to support HEIC/HEIF image uploads via sharp.
- Update backend URL in frontend to use 'photobackend.beachpartyballoons.com'.
- Update CORS whitelist to include the new backend hostname.
- Stage user's change to docker-compose.yml exposing port 5001.
2025-11-24 19:05:14 -05:00
962201975b fix: Resolve CORS issue for photo uploads
- Forces frontend to use HTTP for backend requests to prevent mixed content errors.
- Tightens backend CORS policy to a whitelist of allowed origins.
2025-11-24 16:39:19 -05:00
5053cbcf44 refactor: Reorganize project structure and clean up repository
This commit reflects an intentional reorganization of the project.

- Deletes obsolete root-level files.
- Restructures the admin and gallery components.
- Tracks previously untracked application modules.
2025-11-24 15:15:35 -05:00
e4240d3f02 feat: Implement UI/UX and code efficiency improvements for gallery and admin pages
This commit includes the following changes:

Gallery Page (gallery.html):
- Moved inline CSS to gallery.css for better organization and caching.
- Implemented a skeleton loader to improve perceived loading performance.
- Added a 'No results' message when search/filter yields no photos.
- Enhanced responsive image handling in the modal to load full-resolution images.

Admin Page (admin/index.html):
- Moved inline CSS to admin.css for better organization and caching.
- Fixed an aesthetic issue with the hover style on the 'Clear selection' button.
- Introduced a confirmation modal for bulk delete operations to prevent accidental data loss.
- Implemented a progress bar for file uploads, providing better user feedback.
2025-11-24 15:14:00 -05:00
cdd8ccb0e5 feat: Add docker-compose for easier application management
This commit introduces a `docker-compose.yml` file to simplify the
process of building, running, and managing the application.

- Defines the `bpb-website` service with build context, port mapping,
  and environment variables.
- Mounts a volume for `update.json` to ensure data persistence across
  container restarts.
- Sets `restart: always` to ensure the service is automatically
  restarted if it goes down.
2025-11-13 12:14:34 -05:00
72e9de96e4 feat: Containerize application with Docker and improve admin error handling
This commit introduces Docker support for the application to ensure a consistent
and reproducible environment across different deployment targets.

- Added  for building a Docker image of the application.
- Added  to exclude unnecessary files from the Docker image.
- Improved error handling in  to provide more descriptive messages
  when the server returns an unexpected response, aiding in debugging.
- Included  changes, likely from local testing.
2025-11-13 11:31:58 -05:00
91885d5ff5 Fix: Use relative URL for API requests in admin UI
Changed the  request URL in  from an absolute path
() to a relative path
().

This ensures that the API request is always sent to the same domain
that the admin page is loaded from, resolving CORS and NetworkError
issues when accessing the UI from a production FQDN or a live server
with a different port. This change relies on a correctly configured
reverse proxy in the production environment.
2025-11-12 15:07:05 -05:00
b8c8a1a45f Fix: Admin UI communication and security issues resolved 2025-11-12 14:52:35 -05:00
74aa30636c Refactor: Harden for Production
This commit refactors the Node.js server to be production-ready.

- **Strict Production Environment:** The server now checks for . If it is set, the server will refuse to start unless a secure  is provided as an environment variable. This prevents running with the insecure default password in production.
- **Logging:** Added basic logging for successful status updates and failed login attempts.
- **NPM Scripts:** Added a  script to  for starting the server in production mode ().
2025-11-12 14:26:11 -05:00
07b83c7ae8 Feature: Create Admin UI with Node.js Backend
This commit introduces a web-based admin UI to manage the store's status, backed by a simple Node.js/Express server for file writing.

Key features:
- **Admin UI (, ):** A form to update the scrolling message and closed status. It provides a user-friendly experience with loading states, in-page feedback, and change detection.
- **Node.js Backend ():** A simple Express server that serves the static site and provides a  endpoint. This endpoint receives data from the admin UI, authenticates it, and writes it to .
- **Enhanced Security:** The password is no longer hardcoded in the client-side JavaScript. Authentication is handled server-side, and the password is read from a  file for local development or an environment variable in production.
- **Project Setup (, ):** The project is now a formal Node.js project with dependencies (, , ) and a  file to exclude .
2025-11-12 14:19:34 -05:00
721bf65ed3 Feature: Implement store open/closed status with override
This commit introduces functionality to display the store's open/closed status based on a schedule, with an override mechanism for holidays or emergencies.

Changes include:
- : Added IDs to hours paragraphs for easier manipulation.
- : Refactored  to be more robust and moved its logic to  to prevent race conditions. Removed  for status updates from . Fixed lightbox navigation.
- : Added  (boolean) and  (string) fields to allow overriding the default status.
- : Consolidated all status logic. It now acts as a gatekeeper:
  - If  in  is , it displays  and ensures hours are visible.
  - If  is , it runs the scheduled open/closed logic (originally from ) and updates the status every minute, ensuring hours are always visible.
- : Reverted accidental changes and ensured only necessary status-related styles were added.

This ensures:
- The store's current open/closed status is always displayed.
- An override message can be shown for special closures.
- Store hours are always visible.
2025-11-12 13:57:52 -05:00
0505f0a641 add url for eshop 2025-10-15 14:22:43 -04:00
5c936b2b53 Merge branch 'main' of https://gitea.chrisedwards.tech/chris/bpb-website 2025-10-14 16:23:07 -04:00
29b1e92ea9 update color url 2025-10-14 16:23:04 -04:00
a0a184236c add url generator 2025-10-04 18:52:18 -04:00
c02e7fb4b6 add plausible script injector 2025-09-19 10:08:28 -04:00
1da82489c6 Uncomment logo 2025-09-07 16:55:42 -04:00
ce6f48f5a4 Rearrange colors 2025-09-07 16:51:59 -04:00
ae529862e6 fix link share logic 2025-09-07 20:28:47 +00:00
5011812385 fix mobile layout, update icons, fix colors 2025-09-07 16:12:39 -04:00
33a665294c update stone color 2025-09-04 16:43:38 -04:00
be017ded2b fix nav active 2025-08-30 18:04:17 -04:00
9951904e6d fix galery color links 2025-08-30 18:00:20 -04:00
b4da98f40d add plausible link 2025-08-30 17:55:37 -04:00
5cbc7c1190 add color to menu 2025-08-30 17:48:58 -04:00
c2476135ff comment out metrics - until fix 2025-08-23 06:33:24 -04:00
f7dab87c76 fixed body padding css 2025-07-25 22:33:01 -04:00
d444bbb49a updated links for prod 2025-07-25 22:27:57 -04:00
8253b53b6f added main script and pastel magenta 2025-07-17 10:38:00 -04:00
eaf3bd55f0 added missing colors and fixed crop on a few 2025-07-16 16:46:03 -04:00
ad6effd470 move color order 2025-07-16 15:22:15 -04:00
507d085093 fixed chrome and added pearl colors 2025-07-16 15:11:01 -04:00
9aa20b0da0 main site css link 2025-07-15 14:09:24 -04:00
2a07aca10a fixed mobile button layout 2025-07-14 13:14:24 -04:00
3b52b90e5c fixed drop shadows, and shine 2025-07-14 12:43:56 -04:00
861d281db4 added sharing and local storage 2025-07-13 23:00:19 -04:00
278d152fc1 new balloon mask 2025-07-13 20:55:58 -04:00
2532f69e74 added all colors but pearl 2025-07-01 21:27:20 -04:00
17388229b4 fixed shine on chrome based browsers 2025-07-01 19:23:36 -04:00
e53040d55f shorter string 2025-06-30 21:04:45 -04:00
f2f6397deb balloon svg 2025-06-30 20:31:52 -04:00
0560db4318 new balloon shape 2025-06-30 20:30:57 -04:00
f21e29dd2a space grey 2025-06-30 18:58:51 -04:00
4c81c904b1 mask 2025-06-30 18:44:54 -04:00
6769af994f pics 2025-06-30 18:43:03 -04:00
f433386f6a pics 2025-06-30 18:42:56 -04:00
e6b2014783 pictures 2025-06-30 18:30:24 -04:00
0f8383f0a3 added and fixed chrome. updated animations and string 2025-06-30 18:06:18 -04:00
126f7b05f1 added chrome and balloon strings. updated colors 2025-06-29 23:57:17 -04:00
ac2e0b75b2 updated colors 2025-06-29 21:39:57 -04:00
637242021f added background and animation 2025-06-29 08:23:22 -04:00
ae77418596 inital commit 2025-06-28 21:15:44 -04:00
07c57999b3 added update ticker 2025-06-25 20:26:01 -04:00
6462d153e4 added alyssa to about 2025-06-08 22:23:52 -04:00
40c422c9e4 typo 2025-05-05 15:56:48 -04:00
f15aac5f17 logo to webp 2025-03-17 21:33:13 -04:00
c83490d4c9 remove extra font code, add meta description 2025-03-17 21:14:35 -04:00
dee52d9b0c fix contact us button link 2025-03-05 22:40:57 -05:00
160370eb93 remove ref to index.html 2025-03-04 18:47:10 -05:00
fa6a499de8 update open status js 2025-03-03 09:16:46 -05:00
3e895307d9 gallery img is link, add open/closed sign 2025-03-02 22:19:49 -05:00
0ce88f7961 add metrics for gallery pages 2025-03-02 19:55:39 -05:00
d77d46d358 added phone, address, and location to contact page 2025-03-02 10:14:23 -05:00
7245e97034 forgot to update terms page 2025-03-02 10:10:24 -05:00
fa1e2ba5ff update metrics and form popup 2025-03-02 10:07:56 -05:00
6304066cd6 clean up old files 2025-03-02 09:59:25 -05:00
cf995f2e80 clean up old files 2025-03-02 09:59:13 -05:00
6e09f0a32c add gitignore 2025-03-02 09:54:22 -05:00
ec1897f247 add rotate script 2025-02-26 21:26:50 -05:00
50aed702fa add .gitattributes 2025-02-26 21:26:19 -05:00
81039f5bcf update convert scripts and fixed card title size 2025-02-21 07:36:28 -05:00
f6141b0047 center and fit modal 2025-02-20 21:11:43 -05:00
a2549ff7db fix bulma modal 2025-02-20 20:49:31 -05:00
664c95820f fix modal mobile size 2025-02-20 11:35:21 -05:00
58a3275a49 update bulma modal 2025-02-20 11:13:15 -05:00
797acae974 Merge branch 'main' of https://gitea.chrisedwards.tech/chris/bpb-website
delete requirements.txt
2025-02-20 09:51:46 -05:00
0fb4e0af5c adjust back to top button 2025-02-20 09:48:34 -05:00
537487924b Remove requirements.txt 2025-02-20 07:42:42 -05:00
e47e495911 add lazy loading on gallery 2025-02-20 00:11:12 -05:00
b60e1044e1 add back to top button on all pages 2025-02-20 00:07:26 -05:00
169d1977b4 fix nav on mobile in gallery 2025-02-19 23:45:45 -05:00
d656f79bf2 updated gallery convert code 2025-02-19 22:47:03 -05:00
d019a24c3d final update for gallery 2025-02-19 22:13:40 -05:00
681569e5b3 adjust main contact button 2025-02-18 14:25:58 -05:00
3208b58067 update FAQ 2025-02-18 14:07:31 -05:00
c0634c0971 add metrics 2025-02-18 13:30:36 -05:00
a880d6bc8a contact form now work! 2025-02-18 12:05:50 -05:00
8da66e71a9 another form test - iframe 2025-02-18 09:12:11 -05:00
e74a75e3a4 test form 2025-02-18 09:00:28 -05:00
70560553cc add social links for every page 2025-02-17 19:15:19 -05:00
aa627267cf one more.... 2025-02-17 11:26:26 -05:00
75d827d912 last batch, hopefully 2025-02-17 11:26:04 -05:00
a8db026382 more photos still (coulndn't fit in one commit 2025-02-17 11:24:44 -05:00
eb203fe365 add even more photos 2025-02-17 11:24:10 -05:00
9302d65dcf add more photos 2025-02-17 11:22:09 -05:00
2723aea2a3 add photos 2025-02-17 11:21:36 -05:00
d44eb04a5a add assets for favicon and logo 2025-02-17 11:19:55 -05:00
97d68cc5ba remove extra footer tag 2025-02-17 11:16:35 -05:00
4db9d12743 add bash scripts for gallery generation 2025-02-17 11:15:49 -05:00
b940a47c0d mastodon verify 2025-02-15 21:17:30 -05:00
72b5d0da7a added gallery scripts for all folders 2025-02-11 00:05:48 -05:00
95d2cbfccb added dynamic script for gallery generation 2025-02-10 17:02:21 -05:00
f2e1d0ea12 gallery work 2025-02-10 11:05:20 -05:00
69b83e0e87 add favicon, started FAQ page 2025-02-09 16:20:16 -05:00
7148dcbe0b add about us text 2025-02-09 09:29:39 -05:00
53e717fedc jotform contact us (temporary) added pages, fixed links 2025-02-06 15:56:48 -05:00
37d7563b69 typo php mail script 2025-01-13 21:27:50 -05:00
a0734d27c9 add contact form 2025-01-13 09:29:58 -05:00
9400e3607e comment outcontact form 2025-01-09 15:00:35 -05:00
9faf973d03 add contact - going to test 2025-01-08 23:05:23 -05:00
b3f940074f add images to index 2025-01-08 21:42:33 -05:00
033addb7d8 add footer 2025-01-08 20:54:24 -05:00
759c4efeed add contact info 2025-01-08 01:40:36 -05:00
34ec1f04a9 add hero, nav links, start contact 2025-01-07 22:12:02 -05:00
80126d1b36 inital commit 2025-01-05 20:26:18 -05:00
82b0c8b0b0 Initial commit 2025-01-05 20:10:42 -05:00
2293 changed files with 331258 additions and 615 deletions

View File

@ -1,49 +1,16 @@
# ─── Square API ──────────────────────────────────────────────────────────────── # ── Root .env (fallback for Docker Compose < v2.24) ───────────────────────────
# Get these from https://developer.squareup.com/apps #
SQUARE_ACCESS_TOKEN=your_square_access_token_here # Docker Compose v2.24+ reads build env_file directly from estore/.env — you
SQUARE_LOCATION_ID=your_square_location_id_here # should not need this file at all on a modern install.
# "sandbox" or "production" #
SQUARE_ENVIRONMENT=sandbox # If your Compose is older and the shop shows "Online payment is not
# configured", copy the four NEXT_PUBLIC_* lines from estore/.env into this
# These are exposed to the browser — use your Square Application ID (not access token) # file so Compose can bake them into the Next.js build:
# and the same location ID as above. #
NEXT_PUBLIC_SQUARE_APP_ID=sandbox-sq0idb-your_app_id_here # NEXT_PUBLIC_SQUARE_APP_ID=
NEXT_PUBLIC_SQUARE_LOCATION_ID=your_square_location_id_here # NEXT_PUBLIC_SQUARE_LOCATION_ID=
# "sandbox" or "production" — controls which Square JS SDK URL is loaded # NEXT_PUBLIC_SQUARE_ENVIRONMENT=production
NEXT_PUBLIC_SQUARE_ENVIRONMENT=sandbox # NEXT_PUBLIC_SITE_URL=https://shop.beachpartyballoons.com
# Optional: ID of a Square category (Items > Categories) whose items appear in the shop. #
# If set, only items in this category are shown. Otherwise falls back to src/config/shop-items.json. # All other secrets (access tokens, passwords, etc.) belong only in estore/.env
SQUARE_SHOP_CATEGORY_ID= # — never put them here.
# ─── CalDAV (Nextcloud) ────────────────────────────────────────────────────────
# Your Nextcloud CalDAV base URL — include trailing slash
CALDAV_URL=https://your-nextcloud.example.com/remote.php/dav/calendars/username/
CALDAV_USERNAME=your_nextcloud_username
# Use an app password (Settings > Security > Devices & sessions > App passwords)
CALDAV_PASSWORD=your_nextcloud_app_password
# Display name of the calendar to check for Busy blocks
CALDAV_CALENDAR_NAME=Deliveries
# ─── Email (SMTP — your mail server) ──────────────────────────────────────────
SMTP_HOST=mail.beachpartyballoons.com
SMTP_PORT=587
SMTP_USER=shop@beachpartyballoons.com
SMTP_PASS=your_email_password_here
# Address that receives new-order & slot-conflict alerts (you/staff)
ALERT_EMAIL_TO=you@beachpartyballoons.com
# Sender shown on outgoing emails
ALERT_EMAIL_FROM=shop@beachpartyballoons.com
# ─── Admin panel ───────────────────────────────────────────────────────────────
# Password to access /admin — keep this secret
ADMIN_PASSWORD=change_me_to_something_strong
# Secret token for the cron cache-refresh endpoint (POST /api/cache/refresh)
CACHE_REFRESH_SECRET=change_me_to_something_random
# ─── OSRM (self-hosted routing) ────────────────────────────────────────────────
# Leave blank to use the public demo server (unreliable). Self-host for production:
# https://hub.docker.com/r/osrm/osrm-backend
OSRM_URL=http://localhost:5000
# ─── Site ──────────────────────────────────────────────────────────────────────
NEXT_PUBLIC_SITE_URL=http://localhost:3000

29
.gitignore vendored
View File

@ -1,18 +1,28 @@
# dependencies # Dependencies
node_modules/ node_modules/
.pnp
.pnp.js
# Next.js build output # Next.js
.next/ estore/.next/
out/ estore/out/
# Runtime data — cache and item overrides change at runtime, don't track them # Runtime data
data/catalog-cache.json estore/data/catalog-cache.json
data/item-overrides.json estore/data/item-overrides.json
estore/data/hours.json
estore/data/delivery-rates.json
main-site/photo-gallery-app/backend/uploads/
mongodb_data/
osrm/data/*
!osrm/data/.gitkeep
# Environment variables — never commit these # Environment variables — never commit
.env .env
.env.local .env.local
.env*.local .env*.local
*/.env
*/.env.local
# OS / editor # OS / editor
.DS_Store .DS_Store
@ -26,7 +36,4 @@ npm-debug.log*
# Misc # Misc
.eslintcache .eslintcache
# Raw/duplicate image files — use public/images/ directly
public/images/pics/
*.heic *.heic

View File

@ -1,26 +1,116 @@
services: services:
osrm:
image: osrm/osrm-backend # ── Nginx reverse proxy ───────────────────────────────────────────────────────
container_name: osrm nginx:
restart: unless-stopped image: nginx:alpine
container_name: bpb-nginx
ports:
- "80:80"
volumes:
- ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
depends_on:
- main-site
- estore
restart: always
# ── Main website ─────────────────────────────────────────────────────────────
main-site:
build: ./main-site
container_name: bpb-main
expose:
- "3050"
environment:
NODE_ENV: production
ADMIN_PASSWORD: ${MAIN_ADMIN_PASSWORD}
volumes:
- ./main-site/update.json:/usr/src/app/update.json
restart: always
depends_on:
- gallery-backend
# ── Photo gallery backend ─────────────────────────────────────────────────────
gallery-backend:
build: ./main-site/photo-gallery-app/backend
container_name: bpb-gallery
ports: ports:
- "5002:5000" - "5002:5000"
environment:
MONGO_URI: mongodb://mongodb:27017/photogallery
WATERMARK_URL: http://watermarker:8000/watermark
volumes: volumes:
- ./docker/osrm/data:/data - ./main-site/photo-gallery-app/backend/uploads:/usr/src/app/uploads
command: osrm-routed --algorithm mld /data/connecticut-latest.osrm depends_on:
- mongodb
- watermarker
restart: always
balloons-shop: # ── Watermarker ───────────────────────────────────────────────────────────────
build: . watermarker:
container_name: balloons-shop build: ./main-site/photo-gallery-app/watermarker
container_name: bpb-watermarker
restart: always
# ── MongoDB ───────────────────────────────────────────────────────────────────
mongodb:
image: mongo:latest
container_name: bpb-mongodb
ports: ports:
- "3000:3000" - "27017:27017"
env_file: volumes:
- .env - ./mongodb_data:/data/db
restart: always
# ── eStore (Next.js / Square) ─────────────────────────────────────────────────
# NEXT_PUBLIC_* vars are baked into the JS bundle at build time.
# They are resolved from the root .env file (same dir as this compose file).
estore:
build:
context: ./estore
args:
NEXT_PUBLIC_SQUARE_APP_ID: ${NEXT_PUBLIC_SQUARE_APP_ID}
NEXT_PUBLIC_SQUARE_LOCATION_ID: ${NEXT_PUBLIC_SQUARE_LOCATION_ID}
NEXT_PUBLIC_SQUARE_ENVIRONMENT: ${NEXT_PUBLIC_SQUARE_ENVIRONMENT}
NEXT_PUBLIC_SITE_URL: ${NEXT_PUBLIC_SITE_URL}
container_name: bpb-estore
expose:
- "3000"
env_file: ./estore/.env
volumes:
- ./estore/data:/app/data
restart: unless-stopped restart: unless-stopped
depends_on: depends_on:
- osrm - osrm
healthcheck: healthcheck:
test: ["CMD", "wget", "-qO-", "http://localhost:3000/api/catalog"] test: ["CMD", "node", "-e", "fetch('http://localhost:3000/shop/api/catalog').then(r=>{if(!r.ok)process.exit(1)}).catch(()=>process.exit(1))"]
interval: 30s interval: 30s
timeout: 10s timeout: 10s
retries: 3 retries: 3
# ── OSRM download (runs once, exits) ─────────────────────────────────────────
# Downloads the PBF map file into the shared volume if not already present.
osrm-download:
build:
context: ./osrm
dockerfile: Dockerfile.download
container_name: bpb-osrm-download
volumes:
- ./osrm/data:/data
environment:
OSRM_REGION: connecticut-latest
restart: "no"
# ── OSRM (routing engine) ─────────────────────────────────────────────────────
osrm:
build: ./osrm
container_name: bpb-osrm
expose:
- "5000"
volumes:
- ./osrm/data:/data
environment:
OSRM_REGION: connecticut-latest
OSRM_PROFILE: /opt/car.lua
depends_on:
osrm-download:
condition: service_completed_successfully
restart: unless-stopped

49
estore/.env.example Normal file
View File

@ -0,0 +1,49 @@
# ─── Square API ────────────────────────────────────────────────────────────────
# Get these from https://developer.squareup.com/apps
SQUARE_ACCESS_TOKEN=your_square_access_token_here
SQUARE_LOCATION_ID=your_square_location_id_here
# "sandbox" or "production"
SQUARE_ENVIRONMENT=sandbox
# These are exposed to the browser — use your Square Application ID (not access token)
# and the same location ID as above.
NEXT_PUBLIC_SQUARE_APP_ID=sandbox-sq0idb-your_app_id_here
NEXT_PUBLIC_SQUARE_LOCATION_ID=your_square_location_id_here
# "sandbox" or "production" — controls which Square JS SDK URL is loaded
NEXT_PUBLIC_SQUARE_ENVIRONMENT=sandbox
# Optional: ID of a Square category (Items > Categories) whose items appear in the shop.
# If set, only items in this category are shown. Otherwise falls back to src/config/shop-items.json.
SQUARE_SHOP_CATEGORY_ID=
# ─── CalDAV (Nextcloud) ────────────────────────────────────────────────────────
# Your Nextcloud CalDAV base URL — include trailing slash
CALDAV_URL=https://your-nextcloud.example.com/remote.php/dav/calendars/username/
CALDAV_USERNAME=your_nextcloud_username
# Use an app password (Settings > Security > Devices & sessions > App passwords)
CALDAV_PASSWORD=your_nextcloud_app_password
# Display name of the calendar to check for Busy blocks
CALDAV_CALENDAR_NAME=Deliveries
# ─── Email (SMTP — your mail server) ──────────────────────────────────────────
SMTP_HOST=mail.beachpartyballoons.com
SMTP_PORT=587
SMTP_USER=shop@beachpartyballoons.com
SMTP_PASS=your_email_password_here
# Address that receives new-order & slot-conflict alerts (you/staff)
ALERT_EMAIL_TO=you@beachpartyballoons.com
# Sender shown on outgoing emails
ALERT_EMAIL_FROM=shop@beachpartyballoons.com
# ─── Admin panel ───────────────────────────────────────────────────────────────
# Password to access /admin — keep this secret
ADMIN_PASSWORD=change_me_to_something_strong
# Secret token for the cron cache-refresh endpoint (POST /api/cache/refresh)
CACHE_REFRESH_SECRET=change_me_to_something_random
# ─── OSRM (self-hosted routing) ────────────────────────────────────────────────
# Leave blank to use the public demo server (unreliable). Self-host for production:
# https://hub.docker.com/r/osrm/osrm-backend
OSRM_URL=http://localhost:5000
# ─── Site ──────────────────────────────────────────────────────────────────────
NEXT_PUBLIC_SITE_URL=http://localhost:3000

32
estore/.gitignore vendored Normal file
View File

@ -0,0 +1,32 @@
# dependencies
node_modules/
# Next.js build output
.next/
out/
# Runtime data — cache and item overrides change at runtime, don't track them
data/catalog-cache.json
data/item-overrides.json
# Environment variables — never commit these
.env
.env.local
.env*.local
# OS / editor
.DS_Store
Thumbs.db
.vscode/
.idea/
# Logs
*.log
npm-debug.log*
# Misc
.eslintcache
# Raw/duplicate image files — use public/images/ directly
public/images/pics/
*.heic

View File

@ -10,6 +10,18 @@ WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules COPY --from=deps /app/node_modules ./node_modules
COPY . . COPY . .
ENV NEXT_TELEMETRY_DISABLED=1 ENV NEXT_TELEMETRY_DISABLED=1
# NEXT_PUBLIC_* vars are baked into the JS bundle at build time.
# Pass them as build args from your .env so they're available here.
ARG NEXT_PUBLIC_SQUARE_APP_ID
ARG NEXT_PUBLIC_SQUARE_LOCATION_ID
ARG NEXT_PUBLIC_SQUARE_ENVIRONMENT
ARG NEXT_PUBLIC_SITE_URL
ENV NEXT_PUBLIC_SQUARE_APP_ID=$NEXT_PUBLIC_SQUARE_APP_ID
ENV NEXT_PUBLIC_SQUARE_LOCATION_ID=$NEXT_PUBLIC_SQUARE_LOCATION_ID
ENV NEXT_PUBLIC_SQUARE_ENVIRONMENT=$NEXT_PUBLIC_SQUARE_ENVIRONMENT
ENV NEXT_PUBLIC_SITE_URL=$NEXT_PUBLIC_SITE_URL
RUN npm run build RUN npm run build
# ── Stage 3: Production runner ──────────────────────────────────────────────── # ── Stage 3: Production runner ────────────────────────────────────────────────
@ -26,6 +38,11 @@ COPY --from=builder /app/public ./public
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./ COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
# Ensure the data directory exists and is writable by the nextjs user.
# For bind-mount deployments, the host directory must also be owned by uid 1001:
# sudo chown -R 1001:1001 estore/data
RUN mkdir -p /app/data && chown nextjs:nodejs /app/data
USER nextjs USER nextjs
EXPOSE 3000 EXPOSE 3000
ENV PORT=3000 ENV PORT=3000

View File

@ -0,0 +1,11 @@
{
"order": [
"latex",
"birthday",
"mylar-bouquets",
"graduation",
"letters-and-numbers",
"other"
],
"hidden": []
}

View File

@ -0,0 +1,8 @@
{
"mothers-day": {
"windowStart": "04-10"
},
"graduation": {
"windowStart": "04-01"
}
}

26
estore/docker-compose.yml Normal file
View File

@ -0,0 +1,26 @@
services:
osrm:
image: osrm/osrm-backend
container_name: osrm
restart: unless-stopped
ports:
- "5002:5000"
volumes:
- ./docker/osrm/data:/data
command: osrm-routed --algorithm mld /data/connecticut-latest.osrm
balloons-shop:
build: .
container_name: balloons-shop
ports:
- "3000:3000"
env_file:
- .env
restart: unless-stopped
depends_on:
- osrm
healthcheck:
test: ["CMD", "wget", "-qO-", "http://localhost:3000/api/catalog"]
interval: 30s
timeout: 10s
retries: 3

View File

@ -3,6 +3,10 @@ const isDev = process.env.NODE_ENV === 'development'
/** @type {import('next').NextConfig} */ /** @type {import('next').NextConfig} */
const nextConfig = { const nextConfig = {
output: 'standalone', output: 'standalone',
basePath: '/shop',
env: {
NEXT_PUBLIC_BASE_PATH: '/shop',
},
images: { images: {
remotePatterns: [ remotePatterns: [
{ protocol: 'https', hostname: 'items-images-production.s3.us-west-2.amazonaws.com' }, { protocol: 'https', hostname: 'items-images-production.s3.us-west-2.amazonaws.com' },

View File

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 3.4 KiB

View File

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

Before

Width:  |  Height:  |  Size: 228 KiB

After

Width:  |  Height:  |  Size: 228 KiB

View File

Before

Width:  |  Height:  |  Size: 149 KiB

After

Width:  |  Height:  |  Size: 149 KiB

View File

Before

Width:  |  Height:  |  Size: 160 KiB

After

Width:  |  Height:  |  Size: 160 KiB

View File

Before

Width:  |  Height:  |  Size: 136 KiB

After

Width:  |  Height:  |  Size: 136 KiB

View File

Before

Width:  |  Height:  |  Size: 143 KiB

After

Width:  |  Height:  |  Size: 143 KiB

View File

Before

Width:  |  Height:  |  Size: 2.4 MiB

After

Width:  |  Height:  |  Size: 2.4 MiB

View File

Before

Width:  |  Height:  |  Size: 134 KiB

After

Width:  |  Height:  |  Size: 134 KiB

View File

Before

Width:  |  Height:  |  Size: 114 KiB

After

Width:  |  Height:  |  Size: 114 KiB

View File

Before

Width:  |  Height:  |  Size: 164 KiB

After

Width:  |  Height:  |  Size: 164 KiB

View File

Before

Width:  |  Height:  |  Size: 130 KiB

After

Width:  |  Height:  |  Size: 130 KiB

View File

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 21 KiB

View File

Before

Width:  |  Height:  |  Size: 180 KiB

After

Width:  |  Height:  |  Size: 180 KiB

View File

Before

Width:  |  Height:  |  Size: 149 KiB

After

Width:  |  Height:  |  Size: 149 KiB

View File

Before

Width:  |  Height:  |  Size: 85 KiB

After

Width:  |  Height:  |  Size: 85 KiB

View File

Before

Width:  |  Height:  |  Size: 123 KiB

After

Width:  |  Height:  |  Size: 123 KiB

View File

Before

Width:  |  Height:  |  Size: 146 KiB

After

Width:  |  Height:  |  Size: 146 KiB

View File

Before

Width:  |  Height:  |  Size: 225 KiB

After

Width:  |  Height:  |  Size: 225 KiB

View File

Before

Width:  |  Height:  |  Size: 521 KiB

After

Width:  |  Height:  |  Size: 521 KiB

View File

Before

Width:  |  Height:  |  Size: 213 KiB

After

Width:  |  Height:  |  Size: 213 KiB

View File

Before

Width:  |  Height:  |  Size: 126 KiB

After

Width:  |  Height:  |  Size: 126 KiB

View File

Before

Width:  |  Height:  |  Size: 143 KiB

After

Width:  |  Height:  |  Size: 143 KiB

View File

Before

Width:  |  Height:  |  Size: 137 KiB

After

Width:  |  Height:  |  Size: 137 KiB

View File

Before

Width:  |  Height:  |  Size: 109 KiB

After

Width:  |  Height:  |  Size: 109 KiB

View File

Before

Width:  |  Height:  |  Size: 515 B

After

Width:  |  Height:  |  Size: 515 B

View File

Before

Width:  |  Height:  |  Size: 515 B

After

Width:  |  Height:  |  Size: 515 B

View File

Before

Width:  |  Height:  |  Size: 32 KiB

After

Width:  |  Height:  |  Size: 32 KiB

View File

Before

Width:  |  Height:  |  Size: 80 KiB

After

Width:  |  Height:  |  Size: 80 KiB

View File

Before

Width:  |  Height:  |  Size: 29 KiB

After

Width:  |  Height:  |  Size: 29 KiB

View File

Before

Width:  |  Height:  |  Size: 738 B

After

Width:  |  Height:  |  Size: 738 B

View File

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

View File

Before

Width:  |  Height:  |  Size: 932 KiB

After

Width:  |  Height:  |  Size: 932 KiB

View File

Before

Width:  |  Height:  |  Size: 1.2 MiB

After

Width:  |  Height:  |  Size: 1.2 MiB

View File

Before

Width:  |  Height:  |  Size: 1.5 MiB

After

Width:  |  Height:  |  Size: 1.5 MiB

View File

Before

Width:  |  Height:  |  Size: 877 KiB

After

Width:  |  Height:  |  Size: 877 KiB

View File

Before

Width:  |  Height:  |  Size: 2.2 MiB

After

Width:  |  Height:  |  Size: 2.2 MiB

View File

Before

Width:  |  Height:  |  Size: 827 KiB

After

Width:  |  Height:  |  Size: 827 KiB

View File

Before

Width:  |  Height:  |  Size: 32 KiB

After

Width:  |  Height:  |  Size: 32 KiB

View File

Before

Width:  |  Height:  |  Size: 80 KiB

After

Width:  |  Height:  |  Size: 80 KiB

View File

Before

Width:  |  Height:  |  Size: 29 KiB

After

Width:  |  Height:  |  Size: 29 KiB

View File

Before

Width:  |  Height:  |  Size: 738 B

After

Width:  |  Height:  |  Size: 738 B

View File

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

View File

Before

Width:  |  Height:  |  Size: 689 KiB

After

Width:  |  Height:  |  Size: 689 KiB

View File

Before

Width:  |  Height:  |  Size: 2.8 MiB

After

Width:  |  Height:  |  Size: 2.8 MiB

View File

Before

Width:  |  Height:  |  Size: 3.2 MiB

After

Width:  |  Height:  |  Size: 3.2 MiB

View File

Before

Width:  |  Height:  |  Size: 1.3 MiB

After

Width:  |  Height:  |  Size: 1.3 MiB

View File

Before

Width:  |  Height:  |  Size: 1.1 MiB

After

Width:  |  Height:  |  Size: 1.1 MiB

View File

Before

Width:  |  Height:  |  Size: 1.7 MiB

After

Width:  |  Height:  |  Size: 1.7 MiB

View File

Before

Width:  |  Height:  |  Size: 890 KiB

After

Width:  |  Height:  |  Size: 890 KiB

View File

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 30 KiB

View File

Before

Width:  |  Height:  |  Size: 83 KiB

After

Width:  |  Height:  |  Size: 83 KiB

View File

Before

Width:  |  Height:  |  Size: 41 KiB

After

Width:  |  Height:  |  Size: 41 KiB

View File

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 30 KiB

View File

Before

Width:  |  Height:  |  Size: 83 KiB

After

Width:  |  Height:  |  Size: 83 KiB

View File

Before

Width:  |  Height:  |  Size: 41 KiB

After

Width:  |  Height:  |  Size: 41 KiB

View File

Before

Width:  |  Height:  |  Size: 519 KiB

After

Width:  |  Height:  |  Size: 519 KiB

View File

Before

Width:  |  Height:  |  Size: 739 KiB

After

Width:  |  Height:  |  Size: 739 KiB

View File

Before

Width:  |  Height:  |  Size: 2.0 MiB

After

Width:  |  Height:  |  Size: 2.0 MiB

View File

Before

Width:  |  Height:  |  Size: 1.2 MiB

After

Width:  |  Height:  |  Size: 1.2 MiB

View File

Before

Width:  |  Height:  |  Size: 4.5 KiB

After

Width:  |  Height:  |  Size: 4.5 KiB

View File

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 20 KiB

View File

Before

Width:  |  Height:  |  Size: 8.3 KiB

After

Width:  |  Height:  |  Size: 8.3 KiB

View File

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Some files were not shown because too many files have changed in this diff Show More