From ee4b384238bd657fb2f71ad991138b7058f4804b Mon Sep 17 00:00:00 2001 From: Alireza Hassani Date: Sat, 5 Sep 2026 08:39:56 +0330 Subject: [PATCH] Build Persian SGE Medical website and local product catalog --- .gitignore | 38 + .openai/hosting.json | 1 + .oxfmtrc.json | 13 + .oxlintrc.json | 56 + AGENTS.md | 9 + CLAUDE.md | 1 + CONTEXT.md | 17 + app/about-us/page.tsx | 3 + app/catalog.json | 183 + app/globals.css | 3 + app/layout.tsx | 7 + app/page.tsx | 5 + app/tmas-bama/page.tsx | 2 + components.json | 25 + components/ui/accordion.tsx | 78 + components/ui/alert-dialog.tsx | 187 + components/ui/alert.tsx | 76 + components/ui/aspect-ratio.tsx | 22 + components/ui/attachment.tsx | 207 + components/ui/avatar.tsx | 109 + components/ui/badge.tsx | 52 + components/ui/breadcrumb.tsx | 122 + components/ui/bubble.tsx | 128 + components/ui/button-group.tsx | 87 + components/ui/button.tsx | 58 + components/ui/calendar.tsx | 231 + components/ui/card.tsx | 103 + components/ui/carousel.tsx | 242 + components/ui/chart.tsx | 373 + components/ui/checkbox.tsx | 28 + components/ui/collapsible.tsx | 21 + components/ui/combobox.tsx | 300 + components/ui/command.tsx | 193 + components/ui/context-menu.tsx | 272 + components/ui/dialog.tsx | 159 + components/ui/direction.tsx | 6 + components/ui/drawer.tsx | 228 + components/ui/dropdown-menu.tsx | 272 + components/ui/empty.tsx | 104 + components/ui/field.tsx | 238 + components/ui/hover-card.tsx | 51 + components/ui/input-group.tsx | 158 + components/ui/input-otp.tsx | 86 + components/ui/input.tsx | 20 + components/ui/item.tsx | 201 + components/ui/kbd.tsx | 26 + components/ui/label.tsx | 20 + components/ui/marker.tsx | 71 + components/ui/menubar.tsx | 284 + components/ui/message-scroller.tsx | 130 + components/ui/message.tsx | 92 + components/ui/native-select.tsx | 65 + components/ui/navigation-menu.tsx | 171 + components/ui/pagination.tsx | 133 + components/ui/popover.tsx | 90 + components/ui/progress.tsx | 83 + components/ui/radio-group.tsx | 38 + components/ui/resizable.tsx | 50 + components/ui/scroll-area.tsx | 55 + components/ui/select.tsx | 202 + components/ui/separator.tsx | 25 + components/ui/sheet.tsx | 137 + components/ui/sidebar.tsx | 723 ++ components/ui/skeleton.tsx | 13 + components/ui/slider.tsx | 52 + components/ui/spinner.tsx | 16 + components/ui/switch.tsx | 32 + components/ui/table.tsx | 116 + components/ui/tabs.tsx | 82 + components/ui/textarea.tsx | 18 + components/ui/toast.tsx | 229 + components/ui/toggle-group.tsx | 89 + components/ui/toggle.tsx | 45 + components/ui/tooltip.tsx | 66 + hooks/use-mobile.ts | 21 + lib/utils.ts | 6 + next.config.ts | 3 + package-lock.json | 10697 ++++++++++++++++ package.json | 56 + public/favicon.svg | 1 + public/images/care.jpg | Bin 0 -> 270260 bytes public/images/footer-logo.png | Bin 0 -> 80178 bytes public/images/laboratory.jpg | Bin 0 -> 455561 bytes public/images/logo.png | Bin 0 -> 80178 bytes public/iran-sans.ttf | Bin 0 -> 67344 bytes public/pdfs/24-hour-biological-testing.pdf | Bin 0 -> 276026 bytes public/pdfs/Autoclave-adhesive.pdf | Bin 0 -> 369049 bytes ...oclave-excess-moisture-absorbent-paper.pdf | Bin 0 -> 304007 bytes public/pdfs/BD-Green-Card-Catalog.pdf | Bin 0 -> 253026 bytes public/pdfs/BD-Green-Card-interperate.pdf | Bin 0 -> 550014 bytes public/pdfs/BD-Pack.pdf | Bin 0 -> 310649 bytes public/pdfs/BDS-Test.pdf | Bin 0 -> 315945 bytes public/pdfs/Barcode-indicators.pdf | Bin 0 -> 396379 bytes ...Biological-testing-1hour-fast-response.pdf | Bin 0 -> 285052 bytes ...Cartridges-and-ethylene-oxide-ampoules.pdf | Bin 0 -> 347632 bytes public/pdfs/Class4-Documentary.pdf | Bin 0 -> 277909 bytes public/pdfs/Class5-progressive.pdf | Bin 0 -> 304611 bytes public/pdfs/Class5-steam.pdf | Bin 0 -> 296173 bytes public/pdfs/Class6-Double-Check.pdf | Bin 0 -> 310389 bytes public/pdfs/Hand-scrub-towel.pdf | Bin 0 -> 290379 bytes public/pdfs/Helix-System-Test in-PCD.pdf | Bin 0 -> 290443 bytes .../pdfs/Medical-Macro-Fiber-Fiberglass.pdf | Bin 0 -> 417206 bytes ...al-Nanowave-SMS-SMMS-Sterile-Packaging.pdf | Bin 0 -> 259396 bytes .../Medical-cranone-for-sterile-packaging.pdf | Bin 0 -> 371903 bytes ...anoVoice-Medical-SMS-Sterile-Packaging.pdf | Bin 0 -> 598744 bytes .../Nanoon-is-the-best-sterile-wrapper.pdf | Bin 0 -> 405721 bytes public/pdfs/Roll-Whippec-and-Taiyuk.pdf | Bin 0 -> 356578 bytes .../pdfs/SMS-SMMS-nan-sterile-packaging.pdf | Bin 0 -> 161505 bytes ...Salty-nails-sterile-sponge-scrub-brush.pdf | Bin 0 -> 279379 bytes public/pdfs/Sealer-check.pdf | Bin 0 -> 324232 bytes public/pdfs/Soft-Crepe.pdf | Bin 0 -> 301230 bytes public/pdfs/Sterile-rolls-abs.pdf | Bin 0 -> 271246 bytes public/pdfs/Type-Barcode-Indicator6.pdf | Bin 0 -> 310413 bytes .../Types-of-rolls-and-Sterile-absurd.pdf | Bin 0 -> 286494 bytes tsconfig.json | 46 + vite.config.ts | 61 + 116 files changed, 18819 insertions(+) create mode 100644 .gitignore create mode 100644 .openai/hosting.json create mode 100644 .oxfmtrc.json create mode 100644 .oxlintrc.json create mode 100644 AGENTS.md create mode 100644 CLAUDE.md create mode 100644 CONTEXT.md create mode 100644 app/about-us/page.tsx create mode 100644 app/catalog.json create mode 100644 app/globals.css create mode 100644 app/layout.tsx create mode 100644 app/page.tsx create mode 100644 app/tmas-bama/page.tsx create mode 100644 components.json create mode 100644 components/ui/accordion.tsx create mode 100644 components/ui/alert-dialog.tsx create mode 100644 components/ui/alert.tsx create mode 100644 components/ui/aspect-ratio.tsx create mode 100644 components/ui/attachment.tsx create mode 100644 components/ui/avatar.tsx create mode 100644 components/ui/badge.tsx create mode 100644 components/ui/breadcrumb.tsx create mode 100644 components/ui/bubble.tsx create mode 100644 components/ui/button-group.tsx create mode 100644 components/ui/button.tsx create mode 100644 components/ui/calendar.tsx create mode 100644 components/ui/card.tsx create mode 100644 components/ui/carousel.tsx create mode 100644 components/ui/chart.tsx create mode 100644 components/ui/checkbox.tsx create mode 100644 components/ui/collapsible.tsx create mode 100644 components/ui/combobox.tsx create mode 100644 components/ui/command.tsx create mode 100644 components/ui/context-menu.tsx create mode 100644 components/ui/dialog.tsx create mode 100644 components/ui/direction.tsx create mode 100644 components/ui/drawer.tsx create mode 100644 components/ui/dropdown-menu.tsx create mode 100644 components/ui/empty.tsx create mode 100644 components/ui/field.tsx create mode 100644 components/ui/hover-card.tsx create mode 100644 components/ui/input-group.tsx create mode 100644 components/ui/input-otp.tsx create mode 100644 components/ui/input.tsx create mode 100644 components/ui/item.tsx create mode 100644 components/ui/kbd.tsx create mode 100644 components/ui/label.tsx create mode 100644 components/ui/marker.tsx create mode 100644 components/ui/menubar.tsx create mode 100644 components/ui/message-scroller.tsx create mode 100644 components/ui/message.tsx create mode 100644 components/ui/native-select.tsx create mode 100644 components/ui/navigation-menu.tsx create mode 100644 components/ui/pagination.tsx create mode 100644 components/ui/popover.tsx create mode 100644 components/ui/progress.tsx create mode 100644 components/ui/radio-group.tsx create mode 100644 components/ui/resizable.tsx create mode 100644 components/ui/scroll-area.tsx create mode 100644 components/ui/select.tsx create mode 100644 components/ui/separator.tsx create mode 100644 components/ui/sheet.tsx create mode 100644 components/ui/sidebar.tsx create mode 100644 components/ui/skeleton.tsx create mode 100644 components/ui/slider.tsx create mode 100644 components/ui/spinner.tsx create mode 100644 components/ui/switch.tsx create mode 100644 components/ui/table.tsx create mode 100644 components/ui/tabs.tsx create mode 100644 components/ui/textarea.tsx create mode 100644 components/ui/toast.tsx create mode 100644 components/ui/toggle-group.tsx create mode 100644 components/ui/toggle.tsx create mode 100644 components/ui/tooltip.tsx create mode 100644 hooks/use-mobile.ts create mode 100644 lib/utils.ts create mode 100644 next.config.ts create mode 100644 package-lock.json create mode 100644 package.json create mode 100644 public/favicon.svg create mode 100644 public/images/care.jpg create mode 100644 public/images/footer-logo.png create mode 100644 public/images/laboratory.jpg create mode 100644 public/images/logo.png create mode 100644 public/iran-sans.ttf create mode 100644 public/pdfs/24-hour-biological-testing.pdf create mode 100644 public/pdfs/Autoclave-adhesive.pdf create mode 100644 public/pdfs/Autoclave-excess-moisture-absorbent-paper.pdf create mode 100644 public/pdfs/BD-Green-Card-Catalog.pdf create mode 100644 public/pdfs/BD-Green-Card-interperate.pdf create mode 100644 public/pdfs/BD-Pack.pdf create mode 100644 public/pdfs/BDS-Test.pdf create mode 100644 public/pdfs/Barcode-indicators.pdf create mode 100644 public/pdfs/Biological-testing-1hour-fast-response.pdf create mode 100644 public/pdfs/Cartridges-and-ethylene-oxide-ampoules.pdf create mode 100644 public/pdfs/Class4-Documentary.pdf create mode 100644 public/pdfs/Class5-progressive.pdf create mode 100644 public/pdfs/Class5-steam.pdf create mode 100644 public/pdfs/Class6-Double-Check.pdf create mode 100644 public/pdfs/Hand-scrub-towel.pdf create mode 100644 public/pdfs/Helix-System-Test in-PCD.pdf create mode 100644 public/pdfs/Medical-Macro-Fiber-Fiberglass.pdf create mode 100644 public/pdfs/Medical-Nanowave-SMS-SMMS-Sterile-Packaging.pdf create mode 100644 public/pdfs/Medical-cranone-for-sterile-packaging.pdf create mode 100644 public/pdfs/NanoVoice-Medical-SMS-Sterile-Packaging.pdf create mode 100644 public/pdfs/Nanoon-is-the-best-sterile-wrapper.pdf create mode 100644 public/pdfs/Roll-Whippec-and-Taiyuk.pdf create mode 100644 public/pdfs/SMS-SMMS-nan-sterile-packaging.pdf create mode 100644 public/pdfs/Salty-nails-sterile-sponge-scrub-brush.pdf create mode 100644 public/pdfs/Sealer-check.pdf create mode 100644 public/pdfs/Soft-Crepe.pdf create mode 100644 public/pdfs/Sterile-rolls-abs.pdf create mode 100644 public/pdfs/Type-Barcode-Indicator6.pdf create mode 100644 public/pdfs/Types-of-rolls-and-Sterile-absurd.pdf create mode 100644 tsconfig.json create mode 100644 vite.config.ts diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ef6f899 --- /dev/null +++ b/.gitignore @@ -0,0 +1,38 @@ +# dependencies +/node_modules +/.pnp +.pnp.* +.yarn/* +!.yarn/patches +!.yarn/plugins +!.yarn/releases +!.yarn/versions + +# testing +/coverage + +# next.js +/.next/ +/.vinext/ +/out/ + +# misc +.DS_Store +*.pem + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* +.pnpm-debug.log* + +# local environment +.env* + +# deployment and generated files +.vercel +next-env.d.ts +/dist/ +/.wrangler/ +/outputs/ +/work/ diff --git a/.openai/hosting.json b/.openai/hosting.json new file mode 100644 index 0000000..70ca8b6 --- /dev/null +++ b/.openai/hosting.json @@ -0,0 +1 @@ +{"project_id":"appgprj_6a9ba2dadd448191bc030f95aa2edb04","static":{"directory":"out"},"d1":null,"r2":null} diff --git a/.oxfmtrc.json b/.oxfmtrc.json new file mode 100644 index 0000000..2acd235 --- /dev/null +++ b/.oxfmtrc.json @@ -0,0 +1,13 @@ +{ + "$schema": "./node_modules/oxfmt/configuration_schema.json", + "singleQuote": true, + "printWidth": 80, + "sortPackageJson": false, + "ignorePatterns": [ + "package-lock.json", + "pnpm-lock.yaml", + "yarn.lock", + "bun.lock", + "bun.lockb" + ] +} diff --git a/.oxlintrc.json b/.oxlintrc.json new file mode 100644 index 0000000..cb35cb8 --- /dev/null +++ b/.oxlintrc.json @@ -0,0 +1,56 @@ +{ + "$schema": "./node_modules/oxlint/configuration_schema.json", + "plugins": [ + "eslint", + "typescript", + "unicorn", + "oxc", + "react", + "import", + "jsx-a11y", + "nextjs" + ], + "categories": { + "correctness": "error" + }, + "env": { + "builtin": true, + "browser": true, + "node": true + }, + "options": { + "typeAware": true, + "typeCheck": true + }, + "ignorePatterns": [ + ".next/**", + ".vinext/**", + "out/**", + "build/**", + "dist/**", + "coverage/**", + "next-env.d.ts" + ], + "rules": { + "no-array-constructor": "error", + "no-var": "error", + "prefer-const": "error", + "prefer-rest-params": "error", + "prefer-spread": "error", + "import/no-anonymous-default-export": "warn", + "react/display-name": "error", + "react/jsx-no-comment-textnodes": "error", + "react/no-unescaped-entities": "error", + "react/react-compiler": "error", + "react/require-render-return": "error", + "react/rules-of-hooks": "error", + "typescript/ban-ts-comment": "error", + "typescript/no-deprecated": "error", + "typescript/no-empty-object-type": "error", + "typescript/no-explicit-any": "error", + "typescript/no-namespace": "error", + "typescript/no-require-imports": "error", + "typescript/no-unnecessary-type-constraint": "error", + "typescript/no-unsafe-function-type": "error" + } +} diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..643577d --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,9 @@ + + +# This is NOT the Next.js you know + +This version has breaking changes — APIs, conventions, and file structure may all differ from your training data. Read the relevant guide in `node_modules/next/dist/docs/` (resolved from this file's directory; in monorepos the `next` package may not be visible from the repo root) before writing any code. Heed deprecation notices. + +This block is written and re-added by `next dev` — verify at `node_modules/next/dist/server/lib/generate-agent-files.js`. Removing it from a diff only re-creates the uncommitted change; committing it with your work keeps the tree clean. + + diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..43c994c --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1 @@ +@AGENTS.md diff --git a/CONTEXT.md b/CONTEXT.md new file mode 100644 index 0000000..3c0dbf2 --- /dev/null +++ b/CONTEXT.md @@ -0,0 +1,17 @@ +# SGE Medical Group +Updated 2026-09-05 for initial website creation request. + +## User brief +Source: https://api.meshkee.com/api/v1/public/ai-prompts/sge-medical-group/basic-create/5d795143f6b147770dabe5bb +Build only homepage, about us, contact us in Persian, RTL, Next.js, flat design with original palette. Use existing sgemed.com content and logo, supplied ImageSamples. Download all PDFs and associate products. Update this context when future prompts materially change the project. + +## Project +Application in `site/`. Actual Next.js 16 App Router, React 19, static export to `out/`. Commands in site: npm run dev / npm run build. Sites starter retained with unused component dependencies; Next.js replaces vinext execution per explicit brief. Cyan, white, charcoal; local Iran Sans font; responsive layout. No shopping checkout or invented contact form. +Routes: /, /about-us, /tmas-bama. Product catalog is on homepage. Original contact-page mobile 09389221460 chosen over truncated footer number. + +## Sources and assets +Original: https://www.sgemed.com/, /about-us, /tmas-bama. +Original public PDF URLs all return 404; recovered 29 of 30 from asset host https://meshkee-templates.sas.amin.parminstorage.ir/sites/user_themes/sgemed_Emdko4jewE/assets/uploads/. +Catalog and original provenance/status: site/app/catalog.json. Local PDFs: site/public/pdfs. Missing Barcode-and-sticky-indicator-of-type-4.pdf: product requests catalog via contact page instead of broken download. Do not claim all 30 were downloaded. +Local original logo and footer logo in public/images, font public/iran-sans.ttf. Supplied louis-reed photo used as laboratory.jpg and national-cancer-institute-fd0b-Bl4cFc photo as care.jpg. Preserve ImageSamples originals. +Site ID stored in site/.openai/hosting.json, static output out. Never store hosting credentials in repository. diff --git a/app/about-us/page.tsx b/app/about-us/page.tsx new file mode 100644 index 0000000..dff925e --- /dev/null +++ b/app/about-us/page.tsx @@ -0,0 +1,3 @@ +import Link from 'next/link'; +export const metadata={title:'درباره ما'}; +export default function About(){return <>
ABOUT SGE MEDICAL GROUP

آنچه درباره ما باید بدانید

شرکت مهندسی سلامت گستر اعتماد

از یک ایده در سال ۱۳۸۵

هر روز، بهتر از دیروز.

اولین ایده تشکیل شرکت در سال ۱۳۸۵، با هدف نوآوری، خلاقیت، ایجاد اشتغال و تولید ارزش افزوده شکل گرفت. تجربه کار در حوزه خدمات سلامت، بهداشت، کنترل عفونت و استریلیزاسیون، نگاه ما را تکامل داد.

باور داریم هدف غایی این است که کاری را که بر عهده می‌گیریم، هر روز بهتر از دیروز انجام دهیم و مشکلی از مشکلات مشتریانمان کم کنیم.

مهندس اویسیمدیرعامل
تجهیزات و فعالیت در آزمایشگاه

دانش و تجربه، در خدمت سلامت

اکنون پس از تجربه‌های فراوان، سبدی از محصولات دارای استانداردها و تأییدیه‌های جهانی و مناسب اقتصاد ایران را در زمینه استریلیزاسیون و کنترل عفونت ارائه می‌دهیم. هدف ما بهبود مستمر در سایه دانش و تجربه است.

بهبود مستمر، کلید ماندگاری است.

اعتقادی به تبلیغات غلوآمیز «بهترین» و «بزرگترین» نداریم. معتقدیم هر روز کاری، روزی برای بهتر شدن و بزرگتر شدن است. دنیای امروز، دنیای تغییرات سریع است و نبوغ و تلاش آدمی مرز ندارد.

ما خانواده کوچکی هستیم که با تمرکز بر توسعه دانش و آموزش مهارت‌ها، در کنار همکاران، رقبا و به‌ویژه شما مشتریان عزیز بهتر می‌شویم. تمام تلاشمان را انجام می‌دهیم تا کاری را که بر عهده می‌گیریم به بهترین شکل ممکن به انجام برسانیم و پذیرای نظرات و پیشنهادات شما هستیم.

با ما در ارتباط باشید ←
} diff --git a/app/catalog.json b/app/catalog.json new file mode 100644 index 0000000..7686a5a --- /dev/null +++ b/app/catalog.json @@ -0,0 +1,183 @@ +[ + { + "title": "تست بیولوژیکال 24 ساعته", + "url": "/pdfs/24-hour-biological-testing.pdf", + "source": "https://www.sgemed.com/assets/uploads/24-hour-biological-testing.pdf", + "downloaded": true + }, + { + "title": "تست بیولوژیکال پاسخ سریع 1ساعته", + "url": "/pdfs/Biological-testing-1hour-fast-response.pdf", + "source": "https://www.sgemed.com/assets/uploads/Biological-testing-1hour-fast-response.pdf", + "downloaded": true + }, + { + "title": "BD Green Card Interperate", + "url": "/pdfs/BD-Green-Card-interperate.pdf", + "source": "https://www.sgemed.com/assets/uploads/BD-Green-Card-interperate.pdf", + "downloaded": true + }, + { + "title": "BD Green Card Catalog", + "url": "/pdfs/BD-Green-Card-Catalog.pdf", + "source": "https://www.sgemed.com/assets/uploads/BD-Green-Card-Catalog.pdf", + "downloaded": true + }, + { + "title": "Helix System Test in PCD", + "url": "/pdfs/Helix-System-Test%20in-PCD.pdf", + "source": "https://www.sgemed.com/assets/uploads/Helix-System-Test%20in-PCD.pdf", + "downloaded": true + }, + { + "title": "اندیکاتور بارکددار تایپ 6", + "url": "/pdfs/Type-Barcode-Indicator6.pdf", + "source": "https://www.sgemed.com/assets/uploads/Type-Barcode-Indicator6.pdf", + "downloaded": true + }, + { + "title": "اندیکاتور بارکد و چسبدار تایپ 4", + "url": "https://www.sgemed.com/assets/uploads/Barcode-and-sticky-indicator-of-type-4.pdf", + "source": "https://www.sgemed.com/assets/uploads/Barcode-and-sticky-indicator-of-type-4.pdf", + "downloaded": false, + "error": "HTTP Error 404: Not Found" + }, + { + "title": "تست بوویدیک", + "url": "/pdfs/BDS-Test.pdf", + "source": "https://www.sgemed.com/assets/uploads/BDS-Test.pdf", + "downloaded": true + }, + { + "title": "تست بوویدیک یک", + "url": "/pdfs/BD-Pack.pdf", + "source": "https://www.sgemed.com/assets/uploads/BD-Pack.pdf", + "downloaded": true + }, + { + "title": "چسب اتوکلاو", + "url": "/pdfs/Autoclave-adhesive.pdf", + "source": "https://www.sgemed.com/assets/uploads/Autoclave-adhesive.pdf", + "downloaded": true + }, + { + "title": "کلاس 4 مستندساز", + "url": "/pdfs/Class4-Documentary.pdf", + "source": "https://www.sgemed.com/assets/uploads/Class4-Documentary.pdf", + "downloaded": true + }, + { + "title": "کلاس 5 بخار", + "url": "/pdfs/Class5-steam.pdf", + "source": "https://www.sgemed.com/assets/uploads/Class5-steam.pdf", + "downloaded": true + }, + { + "title": "کلاس 6 دابل چک", + "url": "/pdfs/Class6-Double-Check.pdf", + "source": "https://www.sgemed.com/assets/uploads/Class6-Double-Check.pdf", + "downloaded": true + }, + { + "title": "کلاس 5 پیشرونده", + "url": "/pdfs/Class5-progressive.pdf", + "source": "https://www.sgemed.com/assets/uploads/Class5-progressive.pdf", + "downloaded": true + }, + { + "title": "اندیکاتورهای بارکددار", + "url": "/pdfs/Barcode-indicators.pdf", + "source": "https://www.sgemed.com/assets/uploads/Barcode-indicators.pdf", + "downloaded": true + }, + { + "title": "کاغذ بسته بندی کرپ نرم", + "url": "/pdfs/Soft-Crepe.pdf", + "source": "https://www.sgemed.com/assets/uploads/Soft-Crepe.pdf", + "downloaded": true + }, + { + "title": "SMS & SMMS نانوون بسته بندی استریل", + "url": "/pdfs/SMS-SMMS-nan-sterile-packaging.pdf", + "source": "https://www.sgemed.com/assets/uploads/SMS-SMMS-nan-sterile-packaging.pdf", + "downloaded": true + }, + { + "title": "انواع رول و پوچ استریل", + "url": "/pdfs/Sterile-rolls-abs.pdf", + "source": "https://www.sgemed.com/assets/uploads/Sterile-rolls-abs.pdf", + "downloaded": true + }, + { + "title": "چرا نانوون مدیکال اس ام اس برای بسته بندی استریل وپکینگ؟", + "url": "/pdfs/NanoVoice-Medical-SMS-Sterile-Packaging.pdf", + "source": "https://www.sgemed.com/assets/uploads/NanoVoice-Medical-SMS-Sterile-Packaging.pdf", + "downloaded": true + }, + { + "title": "چرانانوون مدیکال برای بسته بندی استریل؟", + "url": "/pdfs/Medical-cranone-for-sterile-packaging.pdf", + "source": "https://www.sgemed.com/assets/uploads/Medical-cranone-for-sterile-packaging.pdf", + "downloaded": true + }, + { + "title": "کاغذ جاذب رطوبت مازاد اتوکلاو", + "url": "/pdfs/Autoclave-excess-moisture-absorbent-paper.pdf", + "source": "https://www.sgemed.com/assets/uploads/Autoclave-excess-moisture-absorbent-paper.pdf", + "downloaded": true + }, + { + "title": "نانوون بهترین لفافه برای بسته بندی استریل", + "url": "/pdfs/Nanoon-is-the-best-sterile-wrapper.pdf", + "source": "https://www.sgemed.com/assets/uploads/Nanoon-is-the-best-sterile-wrapper.pdf", + "downloaded": true + }, + { + "title": "نانوون مدیکال SMS و SMMS بسته بندی و پکینگ استریل", + "url": "/pdfs/Medical-Nanowave-SMS-SMMS-Sterile-Packaging.pdf", + "source": "https://www.sgemed.com/assets/uploads/Medical-Nanowave-SMS-SMMS-Sterile-Packaging.pdf", + "downloaded": true + }, + { + "title": "انواع رول و پوچ استریل", + "url": "/pdfs/Types-of-rolls-and-Sterile-absurd.pdf", + "source": "https://www.sgemed.com/assets/uploads/Types-of-rolls-and-Sterile-absurd.pdf", + "downloaded": true + }, + { + "title": "رول تویپک و تایوک", + "url": "/pdfs/Roll-Whippec-and-Taiyuk.pdf", + "source": "https://www.sgemed.com/assets/uploads/Roll-Whippec-and-Taiyuk.pdf", + "downloaded": true + }, + { + "title": "سیلر چک", + "url": "/pdfs/Sealer-check.pdf", + "source": "https://www.sgemed.com/assets/uploads/Sealer-check.pdf", + "downloaded": true + }, + { + "title": "ناخن شور+برس اسکراپ اسفنجی استریل", + "url": "/pdfs/Salty-nails-sterile-sponge-scrub-brush.pdf", + "source": "https://www.sgemed.com/assets/uploads/Salty-nails-sterile-sponge-scrub-brush.pdf", + "downloaded": true + }, + { + "title": "حوله اسکراپ دست", + "url": "/pdfs/Hand-scrub-towel.pdf", + "source": "https://www.sgemed.com/assets/uploads/Hand-scrub-towel.pdf", + "downloaded": true + }, + { + "title": "مدیکال ماکرو فایبر کلات", + "url": "/pdfs/Medical-Macro-Fiber-Fiberglass.pdf", + "source": "https://www.sgemed.com/assets/uploads/Medical-Macro-Fiber-Fiberglass.pdf", + "downloaded": true + }, + { + "title": "کارتریج و آمپول اتیله اکساید", + "url": "/pdfs/Cartridges-and-ethylene-oxide-ampoules.pdf", + "source": "https://www.sgemed.com/assets/uploads/Cartridges-and-ethylene-oxide-ampoules.pdf", + "downloaded": true + } +] \ No newline at end of file diff --git a/app/globals.css b/app/globals.css new file mode 100644 index 0000000..580f454 --- /dev/null +++ b/app/globals.css @@ -0,0 +1,3 @@ +@font-face{font-family:Iran;src:url('/iran-sans.ttf') format('truetype');font-display:swap}*{box-sizing:border-box}html{scroll-behavior:smooth;scroll-padding-top:30px}body{margin:0;color:#17323c;background:#fff;font-family:Iran,Tahoma,sans-serif;font-size:16px;line-height:1.9}a{color:inherit;text-decoration:none}button,a,summary{-webkit-tap-highlight-color:transparent}a:focus-visible,summary:focus-visible{outline:3px solid #057e99;outline-offset:5px}a:hover{color:#009cbe}img{max-width:100%;display:block}.wrap{width:min(1280px,90%);margin:auto}.topbar{background:#f0f7f8;font-size:12px;color:#4e6971}.topbar .wrap{display:flex;justify-content:space-between;padding:8px 0}.topbar b{margin-right:18px}.header{display:flex;align-items:center;justify-content:space-between;height:110px;gap:30px}.brand img{width:148px;height:82px;object-fit:contain}.header nav{display:flex;gap:40px;font-size:14px}.button{display:inline-flex;align-items:center;justify-content:center;gap:27px;background:#009fc0;color:white;padding:15px 25px;font-size:14px;border:1px solid #009fc0}.button:hover{background:#087f98;color:white}.button.small{padding:10px 19px}.hero{min-height:540px;display:grid;grid-template-columns:1fr 1fr;background:#eef7f9;direction:ltr}.hero-photo{position:relative;min-height:540px}.hero-photo>img{width:100%;height:100%;object-fit:cover;position:absolute}.hero-photo:after{content:'';position:absolute;inset:0;background:linear-gradient(0deg,#12374160,transparent 60%)}.photo-label{position:absolute;bottom:35px;left:8%;z-index:1;display:flex;align-items:center;gap:20px;color:#fff;direction:rtl}.photo-label small{display:block;font:10px Arial;letter-spacing:2px;margin-top:7px}.cross{font:60px Arial;font-weight:200}.hero-copy{padding:60px 10% 30px 9%;direction:rtl}.eyebrow{display:flex;align-items:center;gap:12px;color:#008eaa;font-size:12px;letter-spacing:1px;font-weight:bold}.eyebrow i{width:28px;height:2px;background:#00a1bf}h1{font-size:46px;line-height:1.75;margin:19px 0;font-weight:700;letter-spacing:-1.5px}h1 em{font-style:normal;color:#009fbe}p{color:#637780;line-height:2.1}.hero-copy>p{font-size:16px}.actions{display:flex;gap:24px;align-items:center;margin-top:30px}.textlink{display:inline-flex;gap:12px;align-items:center;font-size:14px}.hero-bottom{display:flex;gap:15px;align-items:center;border-top:1px solid #d1e4e9;padding-top:24px;margin-top:40px;color:#4d747f;font-size:13px}.hero-bottom small{display:block;color:#78919a;font-size:11px}.categories{display:grid;grid-template-columns:repeat(4,1fr);padding:31px 0;border-bottom:1px solid #dce7e9}.categories>a{display:flex;gap:14px;align-items:center;padding:9px 23px;border-left:1px solid #dce7e9}.categories>a:first-child{padding-right:0}.categories>a:last-child{border:0}.categories svg{color:#009cba;flex-shrink:0}.categories strong{font-size:13px;font-weight:500}.categories small{font:11px Arial;color:#849399;display:block;margin-top:5px}.categories>a>svg:last-child{margin-right:auto}.section{padding:75px 0}.section-heading{display:flex;justify-content:space-between;gap:30px;align-items:center;margin-bottom:30px}h2{font-size:29px;line-height:1.8;margin:12px 0 22px}h3{font-size:17px}.section-heading p{font-size:14px}.catalog{border-top:1px solid #cbdde1}details{border-bottom:1px solid #cbdde1;scroll-margin-top:30px}summary{padding:24px 0;cursor:pointer;display:flex;justify-content:space-between;gap:16px;align-items:center;list-style:none}summary::-webkit-details-marker{display:none}summary>span:last-child{font-size:12px;color:#69818b}.group-title{display:flex;align-items:center;gap:18px}.group-title svg{color:#009fbe}.group-title small{font:12px Arial;color:#82949c}.product-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:1px;background:#dce7e9;border:1px solid #dce7e9;margin-bottom:25px}.product{background:#fff;padding:22px;display:flex;flex-direction:column;min-height:175px}.product:hover{background:#f1fafb}.pdf{font:10px Arial;border:1px solid #b9dce3;width:35px;padding:5px;color:#008fac}.product h3{font-size:14px;font-weight:500;line-height:1.9;margin:18px 0}.download{font-size:11px;color:#008dab;display:flex;justify-content:space-between;margin-top:auto}.education{background:#f0f7f8;padding:65px 0}.split{display:grid;grid-template-columns:1fr 1fr;gap:80px;align-items:center}.split>img{width:100%;height:350px;object-fit:cover}.split p{font-size:15px}.split .textlink{color:#008fab;margin-top:12px}.info-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:40px;margin-top:35px}.info-grid article{border-top:2px solid #00a0bd;padding-top:25px}.info-grid article>span{font:11px Arial;color:#008fa9;letter-spacing:1px}.info-grid p{font-size:14px}.info-grid a{font-size:13px;color:#008fab}.contactband{background:#009fbd;color:white;padding:35px 0}.contactband>.wrap{display:flex;align-items:center;justify-content:space-between;gap:25px}.contactband h2{font-size:24px;margin:0}.contactband p{color:#d4f1f6;font-size:14px;margin:8px 0}.button.white{background:white;color:#007f98;border-color:white;white-space:nowrap}footer{background:#f6f8f9;padding-top:55px}.footergrid{display:grid;grid-template-columns:1.3fr 1fr 1fr;gap:60px;padding-bottom:40px}.footerlogo{width:110px;height:60px;object-fit:contain}.footergrid h3{font-size:14px}.footergrid p,.footergrid a{font-size:13px;color:#69808a}.footergrid a{display:block;margin:10px 0}.copyright{border-top:1px solid #dce5e8;display:flex;justify-content:space-between;padding:20px 0;color:#7a9099;font-size:11px}.pagehead{background:#edf7f9;padding:55px 0}.pagehead h1{font-size:38px;margin-bottom:4px}.pagehead p{margin:0}.prose{max-width:900px}.prose p{line-height:2.5}.quote{border-right:3px solid #009fbd;padding:15px 30px;background:#f0f8fa;margin:35px 0;font-size:22px}.contactcards{display:grid;grid-template-columns:repeat(2,1fr);gap:24px}.contactcard{padding:35px;background:#f1f7f8;border-top:2px solid #009fbd}.contactcard a{display:block;color:#0088a4;font-size:20px;margin:12px 0}.contactcard small{font-size:14px;color:#627b85;display:block}.contactcard h2{font-size:21px} +@media(min-width:1600px){.hero-copy{padding-right:18%}}@media(max-width:1000px){.header nav{gap:20px}.hero-copy{padding:35px 7%}h1{font-size:35px}.actions{gap:14px;flex-wrap:wrap}.categories{grid-template-columns:repeat(2,1fr);gap:15px}.categories>a:nth-child(2){border:0}.categories>a:first-child{padding-right:23px}.product-grid{grid-template-columns:repeat(3,1fr)}.split{gap:35px}}@media(max-width:650px){.topbar .wrap>span{display:none}.topbar .wrap{justify-content:center}.header{height:auto;flex-wrap:wrap;gap:10px;padding-top:12px;padding-bottom:15px}.brand img{width:115px;height:60px}.header nav{order:3;width:100%;justify-content:space-between;font-size:13px;gap:8px;margin-top:10px}.button.small{font-size:12px;padding:8px 12px}.hero{display:flex;flex-direction:column-reverse}.hero-copy{padding:35px 6%}.hero-photo{min-height:280px}h1{font-size:34px}.hero-copy>p{font-size:14px}.hero-bottom{margin-top:25px}.categories{padding:22px 0;gap:10px}.categories>a{padding:8px!important;gap:8px}.categories strong{font-size:11px}.categories small{font-size:9px}.categories svg{width:23px}.categories>a>svg:last-child{display:none}.section{padding:45px 0}.section-heading{display:block}h2{font-size:24px}.group-title{gap:10px;font-size:14px}.group-title small{display:none}summary>span:last-child{font-size:10px}.product-grid{grid-template-columns:repeat(2,1fr)}.product{padding:15px;min-height:180px}.split{grid-template-columns:1fr;gap:25px}.split>img{height:260px}.education{padding:35px 0}.info-grid{grid-template-columns:1fr;gap:20px}.contactband>.wrap{display:block}.contactband h2{font-size:22px}.contactband .button{margin-top:15px}.footergrid{grid-template-columns:1fr 1fr;gap:25px}.footergrid>div:first-child{grid-column:1/-1}.copyright{gap:20px;font-size:9px}.contactcards{grid-template-columns:1fr}.pagehead{padding:30px 0}.pagehead h1{font-size:30px}} +@media(prefers-reduced-motion:reduce){html{scroll-behavior:auto}} diff --git a/app/layout.tsx b/app/layout.tsx new file mode 100644 index 0000000..e2ca71e --- /dev/null +++ b/app/layout.tsx @@ -0,0 +1,7 @@ +import type { Metadata } from 'next'; +import Link from 'next/link'; +import './globals.css'; +export const metadata: Metadata = { title: { default: 'سلامت گستر اعتماد | تجهیزات استریل و کنترل عفونت', template: '%s | سلامت گستر اعتماد' }, description: 'شرکت مهندسی سلامت گستر اعتماد؛ مشاور و مجری استریل و کنترل عفونت. محصولات تخصصی، کاتالوگ‌ها و راه‌های ارتباط با ما.' }; +export default function RootLayout({ children }: Readonly<{ children: React.ReactNode }>) { + return
مشاور و مجری استریل و کنترل عفونتدفتر تهران ۰۲۱ − ۶۶۱۵۷۶۰۹
SGE Medical Groupمشاوره و خرید ↖
{children}
+} diff --git a/app/page.tsx b/app/page.tsx new file mode 100644 index 0000000..c11ed38 --- /dev/null +++ b/app/page.tsx @@ -0,0 +1,5 @@ +import Link from 'next/link'; +import { FlaskConical, ShieldCheck, Package, Microscope, ArrowDownLeft, MoveLeft } from 'lucide-react'; +import catalog from './catalog.json'; +const groups=[{title:'اندیکاتورهای شیمیایی',en:'Chemical indicators',icon:FlaskConical,start:2,end:15},{title:'اندیکاتورهای بیولوژیکال',en:'Biological indicators',icon:Microscope,start:0,end:2},{title:'بسته‌بندی استریل',en:'Sterile packaging',icon:Package,start:15,end:26},{title:'بهداشت و کنترل عفونت',en:'Infection control',icon:ShieldCheck,start:26,end:30}]; +export default function Home(){return <>
محیط آزمایشگاهی و تجهیزات تخصصی
+
دانش، دقت، اعتمادSCIENCE IN SERVICE OF HEALTH
SGE MEDICAL GROUP

اعتماد، نخستین گام
در مسیر سلامت.

راهکارهای تخصصی استریلیزاسیون و کنترل عفونت؛
همراه مراکز درمانی، از انتخاب تا استفاده.

محصولات تخصصی ما آشنایی با سلامت گستر
شرکت مهندسی سلامت گستر اعتمادمشاور و مجری استریل و کنترل عفونت
{groups.map((g,i)=>
{g.title}{g.en}
)}
محصولات تخصصی ما

دقت در انتخاب؛ اطمینان در عملکرد

معرفی محصولات و دریافت کاتالوگ‌های تخصصی
استریل، بسته‌بندی و کنترل عفونت

{groups.map((g,i)=>
{g.title}{g.en}مشاهده محصولات +
)}
فعالیت متخصصان در محیط پزشکی
دانش، پایهٔ مراقبت بهتر

آموزش، کلید توسعه
و تخصص ما است.

دانش استریل و بازفرآوری ابزار پزشکی، دانشی چندبعدی و تخصصی است. کتاب راهنمای جامع استریلیزاسیون، ترجمه گایدلاین ST79، برای فعالان حوزه استریل و کارشناسان کنترل عفونت معرفی شده است.

برای تهیه کتاب با ما تماس بگیرید
استریل و کنترل عفونت

شناخت بهتر، انتخاب آگاهانه‌تر

۰۱ / CHEMICAL

اندیکاتور شیمیایی چیست؟

این نشانگرها معمولاً جامد و کاغذی‌شکل هستند، داخل پک‌های استریل قرار می‌گیرند و در طول فرایند استریلیزاسیون تغییر رنگ می‌دهند.

۰۲ / BIOLOGICAL

اندیکاتور بیولوژیکال چیست؟

این اندیکاتورها حاوی میکروارگانیسم‌های زنده هستند. نتیجه کشت آن‌ها در محیط مرتبط، برای ارزیابی عملکرد فرایند استریلیزاسیون استفاده می‌شود.

۰۳ / DOCUMENTATION

مستندسازی و ردیابی استریل

نرم‌افزار CSSD-DOC برای مستندسازی و ردیابی استریل؛ گذار از دنیای کاغذی به عصر الکترونیک.

دریافت اطلاعات بیشتر ←

برای انتخاب محصول مناسب، همراه شما هستیم.

مشاوره و خرید محصولات تخصصی کنترل عفونت و استریلیزاسیون

ارتباط با کارشناسان
} diff --git a/app/tmas-bama/page.tsx b/app/tmas-bama/page.tsx new file mode 100644 index 0000000..120a5ea --- /dev/null +++ b/app/tmas-bama/page.tsx @@ -0,0 +1,2 @@ +export const metadata={title:'تماس با ما'}; +export default function Contact(){return <>
CONTACT US

با ما در تماس باشید

برای مشاوره و خرید محصولات کنترل عفونت و استریلیزاسیون، همراه شما هستیم.

راه‌های ارتباطی

گفت‌وگو، آغاز یک انتخاب مطمئن

شرکت مهندسی سلامت گستر اعتماد
مشاور و مجری استریل و کنترل عفونت

۰۲ / MOBILE

ارتباط با کارشناسان

آقای مهندس اویسی0912 553 7630خانم مهندس یعقوبی راد0938 922 1460
۰۴ / FAX

شماره فکس

ارسال مکاتبات و اسناد

025 3655 0166
} diff --git a/components.json b/components.json new file mode 100644 index 0000000..f382eb7 --- /dev/null +++ b/components.json @@ -0,0 +1,25 @@ +{ + "$schema": "https://ui.shadcn.com/schema.json", + "style": "base-nova", + "rsc": true, + "tsx": true, + "tailwind": { + "config": "", + "css": "app/globals.css", + "baseColor": "neutral", + "cssVariables": true, + "prefix": "" + }, + "iconLibrary": "lucide", + "rtl": false, + "aliases": { + "components": "@/components", + "utils": "@/lib/utils", + "ui": "@/components/ui", + "lib": "@/lib", + "hooks": "@/hooks" + }, + "menuColor": "default", + "menuAccent": "subtle", + "registries": {} +} diff --git a/components/ui/accordion.tsx b/components/ui/accordion.tsx new file mode 100644 index 0000000..9daf7bf --- /dev/null +++ b/components/ui/accordion.tsx @@ -0,0 +1,78 @@ +import { Accordion as AccordionPrimitive } from '@base-ui/react/accordion'; + +import { cn } from '@/lib/utils'; +import { ChevronDownIcon, ChevronUpIcon } from 'lucide-react'; + +function Accordion({ className, ...props }: AccordionPrimitive.Root.Props) { + return ( + + ); +} + +function AccordionItem({ className, ...props }: AccordionPrimitive.Item.Props) { + return ( + + ); +} + +function AccordionTrigger({ + className, + children, + ...props +}: AccordionPrimitive.Trigger.Props) { + return ( + + + {children} + + + + + ); +} + +function AccordionContent({ + className, + children, + ...props +}: AccordionPrimitive.Panel.Props) { + return ( + +
+ {children} +
+
+ ); +} + +export { Accordion, AccordionItem, AccordionTrigger, AccordionContent }; diff --git a/components/ui/alert-dialog.tsx b/components/ui/alert-dialog.tsx new file mode 100644 index 0000000..46d9eb7 --- /dev/null +++ b/components/ui/alert-dialog.tsx @@ -0,0 +1,187 @@ +'use client'; + +import * as React from 'react'; +import { AlertDialog as AlertDialogPrimitive } from '@base-ui/react/alert-dialog'; + +import { cn } from '@/lib/utils'; +import { Button } from '@/components/ui/button'; + +function AlertDialog({ ...props }: AlertDialogPrimitive.Root.Props) { + return ; +} + +function AlertDialogTrigger({ ...props }: AlertDialogPrimitive.Trigger.Props) { + return ( + + ); +} + +function AlertDialogPortal({ ...props }: AlertDialogPrimitive.Portal.Props) { + return ( + + ); +} + +function AlertDialogOverlay({ + className, + ...props +}: AlertDialogPrimitive.Backdrop.Props) { + return ( + + ); +} + +function AlertDialogContent({ + className, + size = 'default', + ...props +}: AlertDialogPrimitive.Popup.Props & { + size?: 'default' | 'sm'; +}) { + return ( + + + + + ); +} + +function AlertDialogHeader({ + className, + ...props +}: React.ComponentProps<'div'>) { + return ( +
+ ); +} + +function AlertDialogFooter({ + className, + ...props +}: React.ComponentProps<'div'>) { + return ( +
+ ); +} + +function AlertDialogMedia({ + className, + ...props +}: React.ComponentProps<'div'>) { + return ( +
+ ); +} + +function AlertDialogTitle({ + className, + ...props +}: React.ComponentProps) { + return ( + + ); +} + +function AlertDialogDescription({ + className, + ...props +}: React.ComponentProps) { + return ( + + ); +} + +function AlertDialogAction({ + className, + ...props +}: React.ComponentProps) { + return ( + + ); +} + +function CarouselNext({ + className, + variant = 'outline', + size = 'icon-sm', + ...props +}: React.ComponentProps) { + const { orientation, scrollNext, canScrollNext } = useCarousel(); + + return ( + + ); +} + +export { + type CarouselApi, + Carousel, + CarouselContent, + CarouselItem, + CarouselPrevious, + CarouselNext, + useCarousel, +}; diff --git a/components/ui/chart.tsx b/components/ui/chart.tsx new file mode 100644 index 0000000..0680cf0 --- /dev/null +++ b/components/ui/chart.tsx @@ -0,0 +1,373 @@ +'use client'; + +import * as React from 'react'; +import * as RechartsPrimitive from 'recharts'; +import type { TooltipValueType } from 'recharts'; + +import { cn } from '@/lib/utils'; + +// Format: { THEME_NAME: CSS_SELECTOR } +const THEMES = { light: '', dark: '.dark' } as const; + +const INITIAL_DIMENSION = { width: 320, height: 200 } as const; +type TooltipNameType = number | string; + +export type ChartConfig = Record< + string, + { + label?: React.ReactNode; + icon?: React.ComponentType; + } & ( + | { color?: string; theme?: never } + | { color?: never; theme: Record } + ) +>; + +type ChartContextProps = { + config: ChartConfig; +}; + +const ChartContext = React.createContext(null); + +function useChart() { + const context = React.useContext(ChartContext); + + if (!context) { + throw new Error('useChart must be used within a '); + } + + return context; +} + +function ChartContainer({ + id, + className, + children, + config, + initialDimension = INITIAL_DIMENSION, + ...props +}: React.ComponentProps<'div'> & { + config: ChartConfig; + children: React.ComponentProps< + typeof RechartsPrimitive.ResponsiveContainer + >['children']; + initialDimension?: { + width: number; + height: number; + }; +}) { + const uniqueId = React.useId(); + const chartId = `chart-${id ?? uniqueId.replace(/:/g, '')}`; + + return ( + +
+ + + {children} + +
+
+ ); +} + +const ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => { + const colorConfig = Object.entries(config).filter( + ([, config]) => config.theme ?? config.color, + ); + + if (!colorConfig.length) { + return null; + } + + return ( +