initiale Entwicklung

This commit is contained in:
aknuth 2025-01-03 21:26:45 +01:00
parent d47f6e2284
commit 74dbd9dc5a
25 changed files with 1562 additions and 189 deletions

View File

@ -48,13 +48,15 @@
], ],
"tsConfig": "tsconfig.app.json", "tsConfig": "tsconfig.app.json",
"assets": [ "assets": [
"src/assets",
{ {
"glob": "**/*", "glob": "**/*",
"input": "public" "input": "public"
} }
], ],
"styles": [ "styles": [
"src/styles.css" "src/styles.css",
"node_modules/aos/dist/aos.css"
], ],
"scripts": [] "scripts": []
}, },

686
package-lock.json generated
View File

@ -16,6 +16,7 @@
"@angular/platform-browser": "^18.2.0", "@angular/platform-browser": "^18.2.0",
"@angular/platform-browser-dynamic": "^18.2.0", "@angular/platform-browser-dynamic": "^18.2.0",
"@angular/router": "^18.2.0", "@angular/router": "^18.2.0",
"aos": "^2.3.4",
"rxjs": "~7.8.0", "rxjs": "~7.8.0",
"tslib": "^2.3.0", "tslib": "^2.3.0",
"zone.js": "~0.14.10" "zone.js": "~0.14.10"
@ -24,9 +25,26 @@
"@angular-devkit/build-angular": "^18.2.12", "@angular-devkit/build-angular": "^18.2.12",
"@angular/cli": "^18.2.12", "@angular/cli": "^18.2.12",
"@angular/compiler-cli": "^18.2.0", "@angular/compiler-cli": "^18.2.0",
"@types/aos": "^3.0.7",
"autoprefixer": "^10.4.20",
"postcss": "^8.4.49",
"tailwindcss": "^3.4.17",
"typescript": "~5.5.2" "typescript": "~5.5.2"
} }
}, },
"node_modules/@alloc/quick-lru": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz",
"integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/@ampproject/remapping": { "node_modules/@ampproject/remapping": {
"version": "2.3.0", "version": "2.3.0",
"resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz",
@ -186,6 +204,35 @@
} }
} }
}, },
"node_modules/@angular-devkit/build-angular/node_modules/postcss": {
"version": "8.4.41",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.41.tgz",
"integrity": "sha512-TesUflQ0WKZqAvg52PWL6kHgLKP6xB6heTOdoYM0Wt2UHyxNa4K25EZZMgKns3BH1RLVbZCREPpLY0rhnNoHVQ==",
"dev": true,
"funding": [
{
"type": "opencollective",
"url": "https://opencollective.com/postcss/"
},
{
"type": "tidelift",
"url": "https://tidelift.com/funding/github/npm/postcss"
},
{
"type": "github",
"url": "https://github.com/sponsors/ai"
}
],
"license": "MIT",
"dependencies": {
"nanoid": "^3.3.7",
"picocolors": "^1.0.1",
"source-map-js": "^1.2.0"
},
"engines": {
"node": "^10 || ^12 || >=14"
}
},
"node_modules/@angular-devkit/build-angular/node_modules/tslib": { "node_modules/@angular-devkit/build-angular/node_modules/tslib": {
"version": "2.6.3", "version": "2.6.3",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz",
@ -443,6 +490,36 @@
"typescript": ">=5.4 <5.6" "typescript": ">=5.4 <5.6"
} }
}, },
"node_modules/@angular/compiler-cli/node_modules/chokidar": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz",
"integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==",
"dev": true,
"license": "MIT",
"dependencies": {
"readdirp": "^4.0.1"
},
"engines": {
"node": ">= 14.16.0"
},
"funding": {
"url": "https://paulmillr.com/funding/"
}
},
"node_modules/@angular/compiler-cli/node_modules/readdirp": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.0.2.tgz",
"integrity": "sha512-yDMz9g+VaZkqBYS/ozoBJwaBhTbZo3UNYQHNRw1D3UFQB8oHB4uS/tAODO+ZLjGWmUbKnIlOWO+aaIiAxrUWHA==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">= 14.16.0"
},
"funding": {
"type": "individual",
"url": "https://paulmillr.com/funding/"
}
},
"node_modules/@angular/core": { "node_modules/@angular/core": {
"version": "18.2.13", "version": "18.2.13",
"resolved": "https://registry.npmjs.org/@angular/core/-/core-18.2.13.tgz", "resolved": "https://registry.npmjs.org/@angular/core/-/core-18.2.13.tgz",
@ -4082,6 +4159,13 @@
"node": "^16.14.0 || >=18.0.0" "node": "^16.14.0 || >=18.0.0"
} }
}, },
"node_modules/@types/aos": {
"version": "3.0.7",
"resolved": "https://registry.npmjs.org/@types/aos/-/aos-3.0.7.tgz",
"integrity": "sha512-sEhyFqvKauUJZDbvAB3Pggynrq6g+2PS4XB3tmUr+mDL1gfDJnwslUC4QQ7/l8UD+LWpr3RxZVR/rHoZrLqZVg==",
"dev": true,
"license": "MIT"
},
"node_modules/@types/body-parser": { "node_modules/@types/body-parser": {
"version": "1.19.5", "version": "1.19.5",
"resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz",
@ -4730,6 +4814,13 @@
"url": "https://github.com/chalk/ansi-styles?sponsor=1" "url": "https://github.com/chalk/ansi-styles?sponsor=1"
} }
}, },
"node_modules/any-promise": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz",
"integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==",
"dev": true,
"license": "MIT"
},
"node_modules/anymatch": { "node_modules/anymatch": {
"version": "3.1.3", "version": "3.1.3",
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
@ -4757,6 +4848,24 @@
"url": "https://github.com/sponsors/jonschlinkert" "url": "https://github.com/sponsors/jonschlinkert"
} }
}, },
"node_modules/aos": {
"version": "2.3.4",
"resolved": "https://registry.npmjs.org/aos/-/aos-2.3.4.tgz",
"integrity": "sha512-zh/ahtR2yME4I51z8IttIt4lC1Nw0ktsFtmeDzID1m9naJnWXhCoARaCgNOGXb5CLy3zm+wqmRAEgMYB5E2HUw==",
"license": "MIT",
"dependencies": {
"classlist-polyfill": "^1.0.3",
"lodash.debounce": "^4.0.6",
"lodash.throttle": "^4.0.1"
}
},
"node_modules/arg": {
"version": "5.0.2",
"resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz",
"integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==",
"dev": true,
"license": "MIT"
},
"node_modules/argparse": { "node_modules/argparse": {
"version": "2.0.1", "version": "2.0.1",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
@ -5195,6 +5304,16 @@
"node": ">=6" "node": ">=6"
} }
}, },
"node_modules/camelcase-css": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz",
"integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">= 6"
}
},
"node_modules/caniuse-lite": { "node_modules/caniuse-lite": {
"version": "1.0.30001690", "version": "1.0.30001690",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001690.tgz", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001690.tgz",
@ -5241,19 +5360,41 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/chokidar": { "node_modules/chokidar": {
"version": "4.0.3", "version": "3.6.0",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz",
"integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"readdirp": "^4.0.1" "anymatch": "~3.1.2",
"braces": "~3.0.2",
"glob-parent": "~5.1.2",
"is-binary-path": "~2.1.0",
"is-glob": "~4.0.1",
"normalize-path": "~3.0.0",
"readdirp": "~3.6.0"
}, },
"engines": { "engines": {
"node": ">= 14.16.0" "node": ">= 8.10.0"
}, },
"funding": { "funding": {
"url": "https://paulmillr.com/funding/" "url": "https://paulmillr.com/funding/"
},
"optionalDependencies": {
"fsevents": "~2.3.2"
}
},
"node_modules/chokidar/node_modules/glob-parent": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
"integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
"dev": true,
"license": "ISC",
"dependencies": {
"is-glob": "^4.0.1"
},
"engines": {
"node": ">= 6"
} }
}, },
"node_modules/chownr": { "node_modules/chownr": {
@ -5276,6 +5417,12 @@
"node": ">=6.0" "node": ">=6.0"
} }
}, },
"node_modules/classlist-polyfill": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/classlist-polyfill/-/classlist-polyfill-1.2.0.tgz",
"integrity": "sha512-GzIjNdcEtH4ieA2S8NmrSxv7DfEV5fmixQeyTmqmRmRJPGpRBaSnA2a0VrCjyT8iW8JjEdMbKzDotAJf+ajgaQ==",
"license": "Unlicense"
},
"node_modules/clean-stack": { "node_modules/clean-stack": {
"version": "2.2.0", "version": "2.2.0",
"resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz",
@ -5937,6 +6084,20 @@
"dev": true, "dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/didyoumean": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz",
"integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==",
"dev": true,
"license": "Apache-2.0"
},
"node_modules/dlv": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz",
"integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==",
"dev": true,
"license": "MIT"
},
"node_modules/dns-packet": { "node_modules/dns-packet": {
"version": "5.6.1", "version": "5.6.1",
"resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.6.1.tgz", "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.6.1.tgz",
@ -7910,6 +8071,19 @@
} }
} }
}, },
"node_modules/lilconfig": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz",
"integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=14"
},
"funding": {
"url": "https://github.com/sponsors/antonk52"
}
},
"node_modules/lines-and-columns": { "node_modules/lines-and-columns": {
"version": "1.2.4", "version": "1.2.4",
"resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
@ -8068,7 +8242,12 @@
"version": "4.0.8", "version": "4.0.8",
"resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz",
"integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==",
"dev": true, "license": "MIT"
},
"node_modules/lodash.throttle": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz",
"integrity": "sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ==",
"license": "MIT" "license": "MIT"
}, },
"node_modules/log-symbols": { "node_modules/log-symbols": {
@ -8755,6 +8934,18 @@
"node": "^14.17.0 || ^16.13.0 || >=18.0.0" "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
} }
}, },
"node_modules/mz": {
"version": "2.7.0",
"resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz",
"integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==",
"dev": true,
"license": "MIT",
"dependencies": {
"any-promise": "^1.0.0",
"object-assign": "^4.0.1",
"thenify-all": "^1.0.0"
}
},
"node_modules/nanoid": { "node_modules/nanoid": {
"version": "3.3.8", "version": "3.3.8",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz",
@ -9102,6 +9293,26 @@
"url": "https://github.com/fb55/nth-check?sponsor=1" "url": "https://github.com/fb55/nth-check?sponsor=1"
} }
}, },
"node_modules/object-assign": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
"integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/object-hash": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz",
"integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">= 6"
}
},
"node_modules/object-inspect": { "node_modules/object-inspect": {
"version": "1.13.3", "version": "1.13.3",
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.3.tgz", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.3.tgz",
@ -9588,6 +9799,16 @@
"node": ">=6" "node": ">=6"
} }
}, },
"node_modules/pirates": {
"version": "4.0.6",
"resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz",
"integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">= 6"
}
},
"node_modules/piscina": { "node_modules/piscina": {
"version": "4.6.1", "version": "4.6.1",
"resolved": "https://registry.npmjs.org/piscina/-/piscina-4.6.1.tgz", "resolved": "https://registry.npmjs.org/piscina/-/piscina-4.6.1.tgz",
@ -9615,9 +9836,9 @@
} }
}, },
"node_modules/postcss": { "node_modules/postcss": {
"version": "8.4.41", "version": "8.4.49",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.41.tgz", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.49.tgz",
"integrity": "sha512-TesUflQ0WKZqAvg52PWL6kHgLKP6xB6heTOdoYM0Wt2UHyxNa4K25EZZMgKns3BH1RLVbZCREPpLY0rhnNoHVQ==", "integrity": "sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==",
"dev": true, "dev": true,
"funding": [ "funding": [
{ {
@ -9636,13 +9857,87 @@
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"nanoid": "^3.3.7", "nanoid": "^3.3.7",
"picocolors": "^1.0.1", "picocolors": "^1.1.1",
"source-map-js": "^1.2.0" "source-map-js": "^1.2.1"
}, },
"engines": { "engines": {
"node": "^10 || ^12 || >=14" "node": "^10 || ^12 || >=14"
} }
}, },
"node_modules/postcss-import": {
"version": "15.1.0",
"resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz",
"integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==",
"dev": true,
"license": "MIT",
"dependencies": {
"postcss-value-parser": "^4.0.0",
"read-cache": "^1.0.0",
"resolve": "^1.1.7"
},
"engines": {
"node": ">=14.0.0"
},
"peerDependencies": {
"postcss": "^8.0.0"
}
},
"node_modules/postcss-js": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz",
"integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==",
"dev": true,
"license": "MIT",
"dependencies": {
"camelcase-css": "^2.0.1"
},
"engines": {
"node": "^12 || ^14 || >= 16"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/postcss/"
},
"peerDependencies": {
"postcss": "^8.4.21"
}
},
"node_modules/postcss-load-config": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.2.tgz",
"integrity": "sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==",
"dev": true,
"funding": [
{
"type": "opencollective",
"url": "https://opencollective.com/postcss/"
},
{
"type": "github",
"url": "https://github.com/sponsors/ai"
}
],
"license": "MIT",
"dependencies": {
"lilconfig": "^3.0.0",
"yaml": "^2.3.4"
},
"engines": {
"node": ">= 14"
},
"peerDependencies": {
"postcss": ">=8.0.9",
"ts-node": ">=9.0.0"
},
"peerDependenciesMeta": {
"postcss": {
"optional": true
},
"ts-node": {
"optional": true
}
}
},
"node_modules/postcss-loader": { "node_modules/postcss-loader": {
"version": "8.1.1", "version": "8.1.1",
"resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-8.1.1.tgz", "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-8.1.1.tgz",
@ -9745,6 +10040,46 @@
"postcss": "^8.1.0" "postcss": "^8.1.0"
} }
}, },
"node_modules/postcss-nested": {
"version": "6.2.0",
"resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz",
"integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==",
"dev": true,
"funding": [
{
"type": "opencollective",
"url": "https://opencollective.com/postcss/"
},
{
"type": "github",
"url": "https://github.com/sponsors/ai"
}
],
"license": "MIT",
"dependencies": {
"postcss-selector-parser": "^6.1.1"
},
"engines": {
"node": ">=12.0"
},
"peerDependencies": {
"postcss": "^8.2.14"
}
},
"node_modules/postcss-nested/node_modules/postcss-selector-parser": {
"version": "6.1.2",
"resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz",
"integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==",
"dev": true,
"license": "MIT",
"dependencies": {
"cssesc": "^3.0.0",
"util-deprecate": "^1.0.2"
},
"engines": {
"node": ">=4"
}
},
"node_modules/postcss-selector-parser": { "node_modules/postcss-selector-parser": {
"version": "7.0.0", "version": "7.0.0",
"resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.0.0.tgz", "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.0.0.tgz",
@ -9919,6 +10254,26 @@
"node": ">= 0.8" "node": ">= 0.8"
} }
}, },
"node_modules/read-cache": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
"integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==",
"dev": true,
"license": "MIT",
"dependencies": {
"pify": "^2.3.0"
}
},
"node_modules/read-cache/node_modules/pify": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
"integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/readable-stream": { "node_modules/readable-stream": {
"version": "3.6.2", "version": "3.6.2",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
@ -9935,17 +10290,29 @@
} }
}, },
"node_modules/readdirp": { "node_modules/readdirp": {
"version": "4.0.2", "version": "3.6.0",
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.0.2.tgz", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
"integrity": "sha512-yDMz9g+VaZkqBYS/ozoBJwaBhTbZo3UNYQHNRw1D3UFQB8oHB4uS/tAODO+ZLjGWmUbKnIlOWO+aaIiAxrUWHA==", "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
"dev": true,
"license": "MIT",
"dependencies": {
"picomatch": "^2.2.1"
},
"engines": {
"node": ">=8.10.0"
}
},
"node_modules/readdirp/node_modules/picomatch": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": ">= 14.16.0" "node": ">=8.6"
}, },
"funding": { "funding": {
"type": "individual", "url": "https://github.com/sponsors/jonschlinkert"
"url": "https://paulmillr.com/funding/"
} }
}, },
"node_modules/reflect-metadata": { "node_modules/reflect-metadata": {
@ -10377,70 +10744,6 @@
} }
} }
}, },
"node_modules/sass/node_modules/chokidar": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz",
"integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==",
"dev": true,
"license": "MIT",
"dependencies": {
"anymatch": "~3.1.2",
"braces": "~3.0.2",
"glob-parent": "~5.1.2",
"is-binary-path": "~2.1.0",
"is-glob": "~4.0.1",
"normalize-path": "~3.0.0",
"readdirp": "~3.6.0"
},
"engines": {
"node": ">= 8.10.0"
},
"funding": {
"url": "https://paulmillr.com/funding/"
},
"optionalDependencies": {
"fsevents": "~2.3.2"
}
},
"node_modules/sass/node_modules/glob-parent": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
"integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
"dev": true,
"license": "ISC",
"dependencies": {
"is-glob": "^4.0.1"
},
"engines": {
"node": ">= 6"
}
},
"node_modules/sass/node_modules/picomatch": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=8.6"
},
"funding": {
"url": "https://github.com/sponsors/jonschlinkert"
}
},
"node_modules/sass/node_modules/readdirp": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
"integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
"dev": true,
"license": "MIT",
"dependencies": {
"picomatch": "^2.2.1"
},
"engines": {
"node": ">=8.10.0"
}
},
"node_modules/sax": { "node_modules/sax": {
"version": "1.4.1", "version": "1.4.1",
"resolved": "https://registry.npmjs.org/sax/-/sax-1.4.1.tgz", "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.1.tgz",
@ -11244,6 +11547,39 @@
"node": ">=6" "node": ">=6"
} }
}, },
"node_modules/sucrase": {
"version": "3.35.0",
"resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz",
"integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@jridgewell/gen-mapping": "^0.3.2",
"commander": "^4.0.0",
"glob": "^10.3.10",
"lines-and-columns": "^1.1.6",
"mz": "^2.7.0",
"pirates": "^4.0.1",
"ts-interface-checker": "^0.1.9"
},
"bin": {
"sucrase": "bin/sucrase",
"sucrase-node": "bin/sucrase-node"
},
"engines": {
"node": ">=16 || 14 >=14.17"
}
},
"node_modules/sucrase/node_modules/commander": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz",
"integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">= 6"
}
},
"node_modules/supports-color": { "node_modules/supports-color": {
"version": "7.2.0", "version": "7.2.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
@ -11280,6 +11616,58 @@
"node": ">=0.10" "node": ">=0.10"
} }
}, },
"node_modules/tailwindcss": {
"version": "3.4.17",
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.17.tgz",
"integrity": "sha512-w33E2aCvSDP0tW9RZuNXadXlkHXqFzSkQew/aIa2i/Sj8fThxwovwlXHSPXTbAHwEIhBFXAedUhP2tueAKP8Og==",
"dev": true,
"license": "MIT",
"dependencies": {
"@alloc/quick-lru": "^5.2.0",
"arg": "^5.0.2",
"chokidar": "^3.6.0",
"didyoumean": "^1.2.2",
"dlv": "^1.1.3",
"fast-glob": "^3.3.2",
"glob-parent": "^6.0.2",
"is-glob": "^4.0.3",
"jiti": "^1.21.6",
"lilconfig": "^3.1.3",
"micromatch": "^4.0.8",
"normalize-path": "^3.0.0",
"object-hash": "^3.0.0",
"picocolors": "^1.1.1",
"postcss": "^8.4.47",
"postcss-import": "^15.1.0",
"postcss-js": "^4.0.1",
"postcss-load-config": "^4.0.2",
"postcss-nested": "^6.2.0",
"postcss-selector-parser": "^6.1.2",
"resolve": "^1.22.8",
"sucrase": "^3.35.0"
},
"bin": {
"tailwind": "lib/cli.js",
"tailwindcss": "lib/cli.js"
},
"engines": {
"node": ">=14.0.0"
}
},
"node_modules/tailwindcss/node_modules/postcss-selector-parser": {
"version": "6.1.2",
"resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz",
"integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==",
"dev": true,
"license": "MIT",
"dependencies": {
"cssesc": "^3.0.0",
"util-deprecate": "^1.0.2"
},
"engines": {
"node": ">=4"
}
},
"node_modules/tapable": { "node_modules/tapable": {
"version": "2.2.1", "version": "2.2.1",
"resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz",
@ -11405,6 +11793,29 @@
} }
} }
}, },
"node_modules/thenify": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz",
"integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==",
"dev": true,
"license": "MIT",
"dependencies": {
"any-promise": "^1.0.0"
}
},
"node_modules/thenify-all": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz",
"integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==",
"dev": true,
"license": "MIT",
"dependencies": {
"thenify": ">= 3.1.0 < 4"
},
"engines": {
"node": ">=0.8"
}
},
"node_modules/thingies": { "node_modules/thingies": {
"version": "1.21.0", "version": "1.21.0",
"resolved": "https://registry.npmjs.org/thingies/-/thingies-1.21.0.tgz", "resolved": "https://registry.npmjs.org/thingies/-/thingies-1.21.0.tgz",
@ -11488,6 +11899,13 @@
"tree-kill": "cli.js" "tree-kill": "cli.js"
} }
}, },
"node_modules/ts-interface-checker": {
"version": "0.1.13",
"resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz",
"integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==",
"dev": true,
"license": "Apache-2.0"
},
"node_modules/tslib": { "node_modules/tslib": {
"version": "2.8.1", "version": "2.8.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
@ -12246,35 +12664,6 @@
"@esbuild/win32-x64": "0.21.5" "@esbuild/win32-x64": "0.21.5"
} }
}, },
"node_modules/vite/node_modules/postcss": {
"version": "8.4.49",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.49.tgz",
"integrity": "sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==",
"dev": true,
"funding": [
{
"type": "opencollective",
"url": "https://opencollective.com/postcss/"
},
{
"type": "tidelift",
"url": "https://tidelift.com/funding/github/npm/postcss"
},
{
"type": "github",
"url": "https://github.com/sponsors/ai"
}
],
"license": "MIT",
"dependencies": {
"nanoid": "^3.3.7",
"picocolors": "^1.1.1",
"source-map-js": "^1.2.1"
},
"engines": {
"node": "^10 || ^12 || >=14"
}
},
"node_modules/watchpack": { "node_modules/watchpack": {
"version": "2.4.1", "version": "2.4.1",
"resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.1.tgz", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.1.tgz",
@ -12453,44 +12842,6 @@
} }
} }
}, },
"node_modules/webpack-dev-server/node_modules/chokidar": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz",
"integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==",
"dev": true,
"license": "MIT",
"dependencies": {
"anymatch": "~3.1.2",
"braces": "~3.0.2",
"glob-parent": "~5.1.2",
"is-binary-path": "~2.1.0",
"is-glob": "~4.0.1",
"normalize-path": "~3.0.0",
"readdirp": "~3.6.0"
},
"engines": {
"node": ">= 8.10.0"
},
"funding": {
"url": "https://paulmillr.com/funding/"
},
"optionalDependencies": {
"fsevents": "~2.3.2"
}
},
"node_modules/webpack-dev-server/node_modules/glob-parent": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
"integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
"dev": true,
"license": "ISC",
"dependencies": {
"is-glob": "^4.0.1"
},
"engines": {
"node": ">= 6"
}
},
"node_modules/webpack-dev-server/node_modules/http-proxy-middleware": { "node_modules/webpack-dev-server/node_modules/http-proxy-middleware": {
"version": "2.0.7", "version": "2.0.7",
"resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.7.tgz", "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.7.tgz",
@ -12516,32 +12867,6 @@
} }
} }
}, },
"node_modules/webpack-dev-server/node_modules/picomatch": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=8.6"
},
"funding": {
"url": "https://github.com/sponsors/jonschlinkert"
}
},
"node_modules/webpack-dev-server/node_modules/readdirp": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
"integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
"dev": true,
"license": "MIT",
"dependencies": {
"picomatch": "^2.2.1"
},
"engines": {
"node": ">=8.10.0"
}
},
"node_modules/webpack-merge": { "node_modules/webpack-merge": {
"version": "6.0.1", "version": "6.0.1",
"resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-6.0.1.tgz", "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-6.0.1.tgz",
@ -12834,6 +13159,19 @@
"dev": true, "dev": true,
"license": "ISC" "license": "ISC"
}, },
"node_modules/yaml": {
"version": "2.7.0",
"resolved": "https://registry.npmjs.org/yaml/-/yaml-2.7.0.tgz",
"integrity": "sha512-+hSoy/QHluxmC9kCIJyL/uyFmLmc+e5CFR5Wa+bpIhIj85LVb9ZH2nVnqrHoSvKogwODv0ClqZkmiSSaIH5LTA==",
"dev": true,
"license": "ISC",
"bin": {
"yaml": "bin.mjs"
},
"engines": {
"node": ">= 14"
}
},
"node_modules/yargs": { "node_modules/yargs": {
"version": "17.7.2", "version": "17.7.2",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",

View File

@ -17,6 +17,7 @@
"@angular/platform-browser": "^18.2.0", "@angular/platform-browser": "^18.2.0",
"@angular/platform-browser-dynamic": "^18.2.0", "@angular/platform-browser-dynamic": "^18.2.0",
"@angular/router": "^18.2.0", "@angular/router": "^18.2.0",
"aos": "^2.3.4",
"rxjs": "~7.8.0", "rxjs": "~7.8.0",
"tslib": "^2.3.0", "tslib": "^2.3.0",
"zone.js": "~0.14.10" "zone.js": "~0.14.10"
@ -25,6 +26,10 @@
"@angular-devkit/build-angular": "^18.2.12", "@angular-devkit/build-angular": "^18.2.12",
"@angular/cli": "^18.2.12", "@angular/cli": "^18.2.12",
"@angular/compiler-cli": "^18.2.0", "@angular/compiler-cli": "^18.2.0",
"@types/aos": "^3.0.7",
"autoprefixer": "^10.4.20",
"postcss": "^8.4.49",
"tailwindcss": "^3.4.17",
"typescript": "~5.5.2" "typescript": "~5.5.2"
} }
} }

View File

@ -1,16 +1,26 @@
// src/app/app.component.ts
import { CommonModule } from '@angular/common';
import { Component } from '@angular/core'; import { Component } from '@angular/core';
import { RouterLink, RouterLinkActive, RouterOutlet } from '@angular/router';
import * as AOS from 'aos';
@Component({ @Component({
selector: 'app-root', selector: 'app-root',
standalone: true, standalone: true,
imports: [], imports: [CommonModule, RouterOutlet, RouterLink, RouterLinkActive],
template: ` template: `
<h1>Welcome to {{title}}!</h1> <router-outlet></router-outlet>
`
`,
styles: [],
}) })
export class AppComponent { export class AppComponent {
title = 'bay-area-affiliates__'; ngOnInit() {
} AOS.init({
duration: 1000,
once: true
});
}
ngAfterViewInit(): void {
setTimeout(() => {
AOS.refresh();
}, 500);
}
}

View File

@ -1,5 +1,15 @@
import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core'; import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core';
import { provideRouter, Routes } from '@angular/router';
import { AppComponent } from './app.component';
import { BlogPostComponent } from './components/blog-post.component';
import { LandingPageComponent } from './components/landing-page.component';
export const routes: Routes = [
{ path: '', component: LandingPageComponent },
{ path: 'blog/:id', component: BlogPostComponent },
{ path: '**', redirectTo: '' } // Fallback-Route
];
export const appConfig: ApplicationConfig = { export const appConfig: ApplicationConfig = {
providers: [provideZoneChangeDetection({ eventCoalescing: true })] providers: [provideRouter(routes),provideZoneChangeDetection({ eventCoalescing: true })]
}; };

View File

@ -0,0 +1,57 @@
// src/app/components/blog-post/blog-post.component.ts
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { CommonModule } from '@angular/common';
import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
import { BlogService } from '../services/blog.service';
import { FooterComponent } from './footer.component';
import { HeaderComponent } from './header.component';
@Component({
selector: 'app-blog-post',
standalone: true,
imports: [CommonModule, HeaderComponent, FooterComponent],
template: `
<app-header></app-header>
@if(safeContent){
<section class="py-20 bg-gray-200 m-auto" data-aos="fade-up">
<div class="container mx-auto px-6 max-w-[1024px]">
<button (click)="goBack()" class="text-blue-600 hover:underline mb-4"> Back to Latest Insights</button>
<h2 class="text-3xl font-bold mb-4">{{ post?.title }}</h2>
<img [src]="post?.image" [alt]="post?.title" class="rounded-lg mb-6 shadow-lg w-full h-auto object-cover" />
<div class="text-gray-700" [innerHTML]="safeContent"></div>
</div>
</section>
}
<app-footer></app-footer>
`
})
export class BlogPostComponent implements OnInit {
post: any;
safeContent: SafeHtml | null = null;
constructor(
private route: ActivatedRoute,
private router: Router,
private blogService: BlogService,
private sanitizer: DomSanitizer
) {}
ngOnInit() {
const postId = this.route.snapshot.paramMap.get('id');
this.post = this.blogService.getPost(postId);
if (this.post && this.post.content) {
this.safeContent = this.sanitizer.bypassSecurityTrustHtml(this.post.content);
} else {
// Redirect to a 404 page or display an error message
this.router.navigate(['**']);
}
}
ngAfterViewInit(){
}
goBack() {
this.router.navigate(['']);
}
}

View File

@ -0,0 +1,59 @@
// src/app/components/blog/blog.component.ts
import { Component, OnInit } from '@angular/core';
import { CommonModule } from '@angular/common';
import { RouterLink } from '@angular/router';
import { BlogService } from '../services/blog.service';
@Component({
selector: 'app-blog',
standalone: true,
imports: [CommonModule, RouterLink],
template: `
<section id="blog" class="py-20 bg-gray-100" data-aos="fade-up">
<div class="container mx-auto px-6">
<h2 class="text-3xl font-bold text-center">Latest Insights</h2>
<p class="mt-4 text-center text-gray-600">Stay updated with our latest news and articles.</p>
<div class="mt-12 grid grid-cols-1 md:grid-cols-3 gap-8">
<div *ngFor="let post of blogPosts" class="bg-white p-6 rounded-lg shadow hover:shadow-lg transition" data-aos="fade-up">
<img [src]="post.image" [alt]="post.title" class="rounded-t-lg mb-4 w-full h-auto object-cover">
<h3 class="text-xl font-semibold mb-2">{{ post.title }}</h3>
<p class="text-gray-600 mb-4">
{{ getShortContent(post.content) }}
</p>
<a [routerLink]="['/blog', getPostId(post.title)]" class="text-blue-600 hover:underline">Read More</a>
</div>
</div>
</div>
</section>
`
})
export class BlogComponent implements OnInit {
blogPosts: any[] = [];
constructor(private blogService: BlogService) {}
ngOnInit() {
const posts = this.blogService.getAllPosts();
// Convert the blogPosts object to an array
this.blogPosts = Object.keys(posts).map(key => posts[key]);
}
// Function to get a short preview of the content
getShortContent(content: string): string {
const div = document.createElement('div');
div.innerHTML = content;
const text = div.textContent || div.innerText || '';
return text.substring(0, 150) + '...';
}
// Function to get post ID based on the title
getPostId(title: string): string {
const posts = this.blogService.getAllPosts();
for (const id in posts) {
if (posts[id].title === title) {
return id;
}
}
return '1'; // Default to '1' if not found
}
}

View File

@ -0,0 +1,45 @@
// src/app/components/footer/footer.component.ts
import { Component } from '@angular/core';
import { CommonModule } from '@angular/common';
@Component({
selector: 'app-call2action',
standalone: true,
imports: [CommonModule],
template: `<section class="bg-blue-900 text-white py-20" data-aos="fade-up">
<div
class="container mx-auto px-6 flex flex-col md:flex-row items-center justify-between"
>
<!-- Text und Button -->
<div class="md:w-1/2 mb-8 md:mb-0">
<h2 class="text-3xl font-bold">
Ready to Elevate Your IT Infrastructure?
</h2>
<p class="mt-4 text-lg">
Contact Bay Area Affiliates, Inc. today and let our
experts handle your IT needs.
</p>
<a
href="#contact"
class="mt-6 inline-block bg-white text-blue-900 px-6 py-3 rounded-full font-semibold hover:bg-gray-100"
>Get in Touch</a
>
</div>
<!-- Google Map Embed -->
<div class="md:w-1/2 flex justify-center" data-aos="fade-up">
<iframe
src="https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d3331.7894679685755!2d-98.48527228476843!3d27.773756032788047!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x866c1e3b8a9d0c0b%3A0x8f2c1d4c1a5c5b2c!2s1001%20Blucher%20St%2C%20Corpus%20Christi%2C%20TX%2078401%2C%20USA!5e0!3m2!1sen!2sde!4v1672531192743!5m2!1sen!2sde"
width="100%"
height="250"
class="rounded-lg shadow-lg"
style="border: 0"
allowfullscreen=""
loading="lazy"
referrerpolicy="no-referrer-when-downgrade"
>
</iframe>
</div>
</div>
</section>`
})
export class Call2ActionComponent{}

View File

@ -0,0 +1,69 @@
// src/app/components/contact/contact.component.ts
import { Component } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
@Component({
selector: 'app-contact',
standalone: true,
imports: [CommonModule, FormsModule],
template: `
<section id="contact" class="py-20" data-aos="fade-up">
<div class="container mx-auto px-6">
<h2 class="text-3xl font-bold text-center">Get in Touch</h2>
<p class="mt-4 text-center text-gray-600">We're here to help you with all your IT needs.</p>
<div class="mt-12 max-w-lg mx-auto">
<form (ngSubmit)="onSubmit()" class="bg-white p-8 rounded-lg shadow" data-aos="fade-up">
<div class="mb-4">
<label class="block text-gray-700">Name</label>
<input
type="text"
name="name"
[(ngModel)]="formData.name"
class="w-full mt-2 p-3 border rounded"
placeholder="Your Name"
required>
</div>
<div class="mb-4">
<label class="block text-gray-700">Email</label>
<input
type="email"
name="email"
[(ngModel)]="formData.email"
class="w-full mt-2 p-3 border rounded"
placeholder="Your Email"
required>
</div>
<div class="mb-4">
<label class="block text-gray-700">Message</label>
<textarea
name="message"
[(ngModel)]="formData.message"
class="w-full mt-2 p-3 border rounded"
rows="5"
placeholder="Your Message"
required></textarea>
</div>
<button
type="submit"
class="w-full bg-blue-600 text-white p-3 rounded hover:bg-blue-700">
Send Message
</button>
</form>
</div>
</div>
</section>
`
})
export class ContactComponent {
formData = {
name: '',
email: '',
message: ''
};
onSubmit() {
console.log('Form submitted:', this.formData);
// Implement your form submission logic here
}
}

View File

@ -0,0 +1,54 @@
// src/app/components/features/features.component.ts
import { Component } from '@angular/core';
import { CommonModule } from '@angular/common';
@Component({
selector: 'app-features',
standalone: true,
imports: [CommonModule],
template: `
<section id="features" class="py-20" data-aos="fade-up">
<div class="container mx-auto px-6">
<h2 class="text-3xl font-bold text-center">Why Choose Us</h2>
<p class="mt-4 text-center text-gray-600">
Discover the benefits of partnering with Bay Area Affiliates, Inc.
</p>
<div class="mt-12 grid grid-cols-1 md:grid-cols-3 gap-8">
<!-- Feature Item 1 -->
<div class="flex items-center" data-aos="fade-up">
<div class="text-blue-900 text-3xl mr-4">
<i class="fas fa-check-circle"></i>
</div>
<div>
<h3 class="text-xl font-semibold">Experienced Team</h3>
<p class="text-gray-600">Over 25 years of expertise in IT services and solutions.</p>
</div>
</div>
<!-- Feature Item 2 -->
<div class="flex items-center" data-aos="fade-up">
<div class="text-blue-900 text-3xl mr-4">
<i class="fas fa-shield-alt"></i>
</div>
<div>
<h3 class="text-xl font-semibold">Secure Solutions</h3>
<p class="text-gray-600">Top-notch security measures to protect your business data.</p>
</div>
</div>
<!-- Feature Item 3 -->
<div class="flex items-center" data-aos="fade-up">
<div class="text-blue-900 text-3xl mr-4">
<i class="fas fa-cogs"></i>
</div>
<div>
<h3 class="text-xl font-semibold">Customized Solutions</h3>
<p class="text-gray-600">Tailored IT strategies to meet your unique business requirements.</p>
</div>
</div>
</div>
</div>
</section>
`
})
export class FeaturesComponent {}

View File

@ -0,0 +1,209 @@
// src/app/components/footer/footer.component.ts
import { Component } from '@angular/core';
import { CommonModule } from '@angular/common';
@Component({
selector: 'app-footer',
standalone: true,
imports: [CommonModule],
template: `
<footer class="bg-gray-800 text-white py-6" data-aos="fade-up">
<div class="container mx-auto px-6 flex flex-col md:flex-row justify-between items-center">
<div class="mb-4 md:mb-0">
© {{currentYear}} Bay Area Affiliates, Inc. All rights reserved.
</div>
<div class="flex space-x-4 mb-4 md:mb-0">
<a href="#" class="hover:text-blue-400"><i class="fab fa-facebook-f"></i></a>
<a href="#" class="hover:text-blue-400"><i class="fab fa-twitter"></i></a>
<a href="#" class="hover:text-blue-400"><i class="fab fa-linkedin-in"></i></a>
<a href="#" class="hover:text-blue-400"><i class="fab fa-instagram"></i></a>
</div>
<div class="hidden md:flex space-x-4">
<button
class="text-gray-400 hover:text-white focus:outline-none"
(click)="showPrivacyPolicy = true">
Privacy Policy
</button>
<button
class="text-gray-400 hover:text-white focus:outline-none"
(click)="showTerms = true">
Terms of Service
</button>
</div>
</div>
<div class="container mx-auto px-6 mt-4 text-center md:hidden">
<button
class="text-gray-400 hover:text-white mx-2 focus:outline-none"
(click)="showPrivacyPolicy = true">
Privacy Policy
</button>
<span class="text-gray-400">|</span>
<button
class="text-gray-400 hover:text-white mx-2 focus:outline-none"
(click)="showTerms = true">
Terms of Service
</button>
</div>
<!-- Privacy Policy Modal -->
<div *ngIf="showPrivacyPolicy"
class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
<div class="bg-white rounded-lg w-11/12 md:w-3/4 lg:w-1/2 relative overflow-y-auto max-h-screen p-6">
<button
class="absolute top-4 right-4 text-gray-600 hover:text-gray-800 focus:outline-none"
(click)="showPrivacyPolicy = false">
<i class="fas fa-times"></i>
</button>
<div class="p-4 text-gray-800">
<h2 class="text-3xl font-bold mb-4 text-gray-800">Privacy Policy</h2>
<p class="text-gray-700 mb-4">
At Bay Area Affiliates, Inc., we are committed to protecting your privacy.
This Privacy Policy outlines how we collect, use, disclose, and safeguard your
information when you visit our website and use our services.
</p>
<h3 class="text-2xl font-semibold mb-2">
Information We Collect
</h3>
<p class="text-gray-700 mb-4">
We may collect personal information such as your name,
email address, phone number, and other relevant details
when you contact us for our IT support services.
</p>
<h3 class="text-2xl font-semibold mb-2">
How We Use Your Information
</h3>
<p class="text-gray-700 mb-4">
Your information is used to provide and improve our
services, respond to your inquiries, and communicate
important updates. We do not sell or rent your personal
information to third parties.
</p>
<h3 class="text-2xl font-semibold mb-2">Data Security</h3>
<p class="text-gray-700 mb-4">
We implement a variety of security measures to maintain
the safety of your personal information. However, no
method of transmission over the internet or electronic
storage is 100% secure.
</p>
<h3 class="text-2xl font-semibold mb-2">Your Consent</h3>
<p class="text-gray-700 mb-4">
By using our website and services, you consent to our
Privacy Policy.
</p>
<h3 class="text-2xl font-semibold mb-2">
Changes to Our Privacy Policy
</h3>
<p class="text-gray-700 mb-4">
We reserve the right to update our Privacy Policy at any
time. Any changes will be effective immediately upon
posting on this page.
</p>
<h3 class="text-2xl font-semibold mb-2">Contact Us</h3>
<p class="text-gray-700 mb-4">
If you have any questions regarding this Privacy Policy,
please contact us at
<a
href="mailto:info&#64;bayareaaffiliates.com"
class="text-blue-600 underline"
>info&#64;bayareaaffiliates.com</a
>.
</p>
</div>
</div>
</div>
<!-- Terms of Service Modal -->
<div *ngIf="showTerms"
class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
<div class="bg-white rounded-lg w-11/12 md:w-3/4 lg:w-1/2 relative overflow-y-auto max-h-screen p-6">
<button
class="absolute top-4 right-4 text-gray-600 hover:text-gray-800 focus:outline-none"
(click)="showTerms = false">
<i class="fas fa-times"></i>
</button>
<div class="p-4 text-gray-800">
<h2 class="text-3xl font-bold mb-4 text-gray-800">Terms of Service</h2>
<p class="text-gray-700 mb-4">
Welcome to Bay Area Affiliates, Inc. By accessing our website and using our
IT support services, you agree to comply with and be bound by the following
Terms of Service.
</p>
<h3 class="text-2xl font-semibold mb-2">
Service Description
</h3>
<p class="text-gray-700 mb-4">
Bay Area Affiliates, Inc. provides comprehensive IT
support services, including hardware and software
support, network infrastructure, server repair, remote
support, web services, virtualization solutions, and
more.
</p>
<h3 class="text-2xl font-semibold mb-2">
User Responsibilities
</h3>
<p class="text-gray-700 mb-4">
Users are responsible for maintaining the
confidentiality of their account information and for all
activities that occur under their account. Users agree
to provide accurate and complete information when using
our services.
</p>
<h3 class="text-2xl font-semibold mb-2">Payment Terms</h3>
<p class="text-gray-700 mb-4">
All services rendered by Bay Area Affiliates, Inc. are
subject to payment terms agreed upon in the service
contract. Late payments may incur additional fees.
</p>
<h3 class="text-2xl font-semibold mb-2">
Limitation of Liability
</h3>
<p class="text-gray-700 mb-4">
Bay Area Affiliates, Inc. shall not be liable for any
indirect, incidental, or consequential damages arising
from the use of our services. Our total liability is
limited to the amount paid for the services rendered.
</p>
<h3 class="text-2xl font-semibold mb-2">Termination</h3>
<p class="text-gray-700 mb-4">
Either party may terminate the service agreement at any
time with written notice. Upon termination, users must
cease using all services provided by Bay Area
Affiliates, Inc.
</p>
<h3 class="text-2xl font-semibold mb-2">Governing Law</h3>
<p class="text-gray-700 mb-4">
These Terms of Service are governed by and construed in
accordance with the laws of the State of Texas, without
regard to its conflict of law principles.
</p>
<h3 class="text-2xl font-semibold mb-2">
Changes to Terms
</h3>
<p class="text-gray-700 mb-4">
Bay Area Affiliates, Inc. reserves the right to modify
these Terms of Service at any time. Any changes will be
effective immediately upon posting on our website.
Continued use of our services constitutes acceptance of
the updated terms.
</p>
<h3 class="text-2xl font-semibold mb-2">Contact Us</h3>
<p class="text-gray-700 mb-4">
If you have any questions about these Terms of Service,
please contact us at
<a
href="mailto:info&#64;bayareaaffiliates.com"
class="text-blue-600 underline"
>info&#64;bayareaaffiliates.com</a
>.
</p>
</div>
</div>
</div>
</footer>
`
})
export class FooterComponent {
currentYear = new Date().getFullYear();
showPrivacyPolicy = false;
showTerms = false;
}

View File

@ -0,0 +1,50 @@
// src/app/components/header/header.component.ts
import { Component } from '@angular/core';
import { CommonModule } from '@angular/common';
@Component({
selector: 'app-header',
standalone: true,
imports: [CommonModule],
template: `
<header class="bg-white shadow">
<div class="container mx-auto px-6 py-4 flex justify-between items-center">
<div class="text-2xl font-bold text-blue-900">
Bay Area Affiliates, Inc.
</div>
<button
(click)="toggleMenu()"
class="md:hidden text-blue-900 focus:outline-none"
>
<i class="fas fa-bars"></i>
</button>
<nav [class.hidden]="!isMenuOpen" class="hidden md:block w-full md:w-auto">
<ul class="flex flex-col md:flex-row md:space-x-6">
<li>
<a href="#services" class="hover:text-blue-900">Services</a>
</li>
<li>
<a href="#features" class="hover:text-blue-900">Features</a>
</li>
<li>
<a href="#blog" class="hover:text-blue-900">Blog</a>
</li>
<li>
<a
href="#contact"
class="bg-blue-900 text-white px-4 py-2 rounded hover:bg-blue-800"
>Contact</a>
</li>
</ul>
</nav>
</div>
</header>
`
})
export class HeaderComponent {
isMenuOpen = false;
toggleMenu() {
this.isMenuOpen = !this.isMenuOpen;
}
}

View File

@ -0,0 +1,30 @@
// src/app/components/hero/hero.component.ts
import { Component } from '@angular/core';
import { CommonModule } from '@angular/common';
@Component({
selector: 'app-hero',
standalone: true,
imports: [CommonModule],
template: `
<section class="bg-blue-900 text-white" data-aos="fade-up">
<div class="container mx-auto px-6 py-20 flex flex-col-reverse md:flex-row items-center">
<div class="w-full md:w-1/2 mt-8 md:mt-0">
<h1 class="text-4xl md:text-5xl font-bold">
Reliable IT Services for Over 25 Years
</h1>
<p class="mt-4 text-lg">
Providing top-notch Computer & Networking solutions to the Coastal Bend community.
</p>
<a href="#contact" class="mt-6 inline-block bg-white text-blue-900 px-6 py-3 rounded-full font-semibold hover:bg-gray-100">
Get in Touch
</a>
</div>
<div class="w-full md:w-1/2 flex justify-center">
<img src="assets/it-services.webp" alt="IT Services" class="rounded-lg shadow-lg h-[300px] w-[600px] object-cover">
</div>
</div>
</section>
`
})
export class HeroComponent {}

View File

@ -0,0 +1,51 @@
// src/app/components/landing-page/landing-page.component.ts
import { Component, OnInit } from '@angular/core';
import { CommonModule } from '@angular/common';
import * as AOS from 'aos';
import { BlogComponent } from './blog.component';
import { Call2ActionComponent } from './call2action.component';
import { ContactComponent } from './contact.component';
import { FeaturesComponent } from './features.component';
import { FooterComponent } from './footer.component';
import { HeaderComponent } from './header.component';
import { HeroComponent } from './hero.component';
import { ServicesComponent } from './services.component';
@Component({
selector: 'app-landing-page',
standalone: true,
imports: [
CommonModule,
HeaderComponent,
HeroComponent,
ServicesComponent,
FeaturesComponent,
Call2ActionComponent,
BlogComponent,
ContactComponent,
FooterComponent
],
template: `
<app-header></app-header>
<app-hero></app-hero>
<app-services></app-services>
<app-features></app-features>
<app-call2action></app-call2action>
<app-blog></app-blog>
<app-contact></app-contact>
<app-footer></app-footer>
`
})
export class LandingPageComponent {
// ngOnInit() {
// AOS.init({
// duration: 1000,
// once: true
// });
// }
// ngAfterViewInit(): void {
// setTimeout(() => {
// AOS.refresh();
// }, 500);
// }
}

View File

@ -0,0 +1,134 @@
// src/app/components/services/services.component.ts
import { Component } from '@angular/core';
import { CommonModule } from '@angular/common';
@Component({
selector: 'app-services',
standalone: true,
imports: [CommonModule],
template: `
<section id="services" class="py-20 bg-gray-100" data-aos="fade-up">
<div class="container mx-auto px-6">
<h2 class="text-3xl font-bold text-center">Our Services</h2>
<p class="mt-4 text-center text-gray-600">
Comprehensive IT solutions tailored to your business needs.
Read concrete examples of these topics in our
<a href="#blog" class="text-blue-900 underline">Latest Insights</a>
section.
</p>
<div class="mt-12 grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8">
<!-- Service Item 1 -->
<div class="bg-white p-6 rounded-lg shadow hover:shadow-lg transition" data-aos="fade-up">
<div class="text-blue-900 text-4xl mb-4">
<i class="fas fa-window-maximize"></i>
</div>
<h3 class="text-xl font-semibold mb-2">Windows 11 Transition</h3>
<p class="text-gray-600">
Upgrade to Windows 11 before October 2025 to ensure continued security support and take advantage of the latest features.
</p>
</div>
<!-- Service Item 2 -->
<div class="bg-white p-6 rounded-lg shadow hover:shadow-lg transition" data-aos="fade-up">
<div class="text-blue-900 text-4xl mb-4">
<i class="fas fa-globe"></i>
</div>
<h3 class="text-xl font-semibold mb-2">Web Services</h3>
<p class="text-gray-600">
Web design, domain registration, email services, and more to establish and enhance your online presence.
</p>
</div>
<!-- Service Item 3 -->
<div class="bg-white p-6 rounded-lg shadow hover:shadow-lg transition" data-aos="fade-up">
<div class="text-blue-900 text-4xl mb-4">
<i class="fas fa-tachometer-alt"></i>
</div>
<h3 class="text-xl font-semibold mb-2">Performance Upgrades</h3>
<p class="text-gray-600">
Enhance your desktops and laptops with SSDs, maintain your Windows installations, and achieve dramatic performance boosts.
</p>
</div>
<!-- Service Item 4 -->
<div class="bg-white p-6 rounded-lg shadow hover:shadow-lg transition" data-aos="fade-up">
<div class="text-blue-900 text-4xl mb-4">
<i class="fas fa-print"></i>
</div>
<h3 class="text-xl font-semibold mb-2">Printer & Scanner Installation</h3>
<p class="text-gray-600">
Professional installation and configuration of printers and scanners to ensure seamless integration into your workflow.
</p>
</div>
<!-- Service Item 4 -->
<div
class="bg-white p-6 rounded-lg shadow hover:shadow-lg transition"
data-aos="fade-up"
>
<div class="text-blue-900 text-4xl mb-4">
<i class="fas fa-desktop"></i>
</div>
<h3 class="text-xl font-semibold mb-2">
New/Refurbished Desktop Hardware
</h3>
<p class="text-gray-600">
Supply and installation of new or refurbished
desktop hardware, tailored to meet your business
requirements.
</p>
</div>
<!-- Service Item 5 -->
<div
class="bg-white p-6 rounded-lg shadow hover:shadow-lg transition"
data-aos="fade-up"
>
<div class="text-blue-900 text-4xl mb-4">
<i class="fas fa-shield-virus"></i>
</div>
<h3 class="text-xl font-semibold mb-2">VPN Setup</h3>
<p class="text-gray-600">
Configure Virtual Private Networks to allow secure
remote access to your internal network from
anywhere.
</p>
</div>
<!-- Service Item 6 -->
<div
class="bg-white p-6 rounded-lg shadow hover:shadow-lg transition"
data-aos="fade-up"
>
<div class="text-blue-900 text-4xl mb-4">
<i class="fas fa-network-wired"></i>
</div>
<h3 class="text-xl font-semibold mb-2">
Network Infrastructure Support
</h3>
<p class="text-gray-600">
Robust network solutions to ensure connectivity,
security, and efficiency, including routers, access
points, and switches.
</p>
</div>
<!-- Service Item 7 -->
<div
class="bg-white p-6 rounded-lg shadow hover:shadow-lg transition"
data-aos="fade-up"
>
<div class="text-blue-900 text-4xl mb-4">
<i class="fas fa-hdd"></i>
</div>
<h3 class="text-xl font-semibold mb-2">
Network Attached Storage
</h3>
<p class="text-gray-600">
Selection, setup, and maintenance of Network
Attached Storage solutions to provide scalable and
reliable data storage.
</p>
</div>
</div>
</div>
</section>
`
})
export class ServicesComponent {}

View File

@ -0,0 +1,205 @@
// src/app/services/blog.service.ts
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class BlogService {
private blogPosts = {
'1': {
title: 'Upgrade Your HDD to SSD for Enhanced Performance',
image: 'assets/hdd2ssd1.webp',
content: `
<section class="py-20 bg-white" data-aos="fade-up">
<div class="container mx-auto px-6">
<h2 class="text-3xl font-bold text-center mb-6">Upgrade Your HDD to SSD for Enhanced Performance</h2>
<p class="mb-4">In today's fast-paced digital world, the performance of your computer can significantly impact your productivity and overall experience. One of the most effective upgrades you can make is replacing your traditional Hard Disk Drive (HDD) with a Solid State Drive (SSD). Here's why this upgrade is essential and how we at Bay Area Affiliates, Inc. can help you seamlessly transition to a faster, more reliable storage solution.</p>
<h3 class="text-2xl font-semibold mb-2">Hardware Effort and Cost</h3>
<p class="mb-4">Upgrading to a 500GB SSD typically costs around $40 in terms of hardware, making it an affordable investment for a substantial performance boost. Our team ensures that the installation is both cost-effective and tailored to meet your specific needs.</p>
<h3 class="text-2xl font-semibold mb-2">On-Site Installation</h3>
<p class="mb-4">The SSD upgrade can be performed directly at your location, minimizing downtime and ensuring that your setup remains intact. Our technicians are equipped to handle installations efficiently, ensuring a smooth transition.</p>
<h3 class="text-2xl font-semibold mb-2">Installation Time</h3>
<p class="mb-4">The entire process typically takes between 45 minutes to 1 hour, depending on the size of the HDD being replaced and the number of files stored. Our streamlined approach ensures that your computer is up and running with minimal disruption.</p>
<h3 class="text-2xl font-semibold mb-2">Choosing the Right SSD</h3>
<p class="mb-4">It's crucial to select an SSD that matches the data capacity of your existing HDD. We assess your current storage usage to recommend an SSD that provides ample space without unnecessary excess.</p>
<h3 class="text-2xl font-semibold mb-2">Data Transfer and Partitioning</h3>
<p class="mb-4">Once the SSD is installed, we set up the correct partition schema and perform a 1:1 data transfer from your old HDD to the new SSD. This ensures that all your files, applications, and settings are preserved without any data loss.</p>
<h3 class="text-2xl font-semibold mb-2">Seamless Boot and Enhanced Performance</h3>
<p class="mb-4">After the data transfer, your computer will boot from the new SSD. You won't notice the transition, except for the dramatic reduction in boot timesfrom approximately 2-3 minutes down to about 10 seconds. Additionally, application launch times will be significantly faster, enhancing your overall computing experience.</p>
<h3 class="text-2xl font-semibold mb-2">Additional Benefits</h3>
<ul class="list-disc list-inside text-gray-700 mb-4">
<li><strong>Increased Reliability:</strong> SSDs have no moving parts, reducing the risk of mechanical failures.</li>
<li><strong>Energy Efficiency:</strong> SSDs consume less power, contributing to longer battery life in laptops.</li>
<li><strong>Quiet Operation:</strong> Without moving parts, SSDs operate silently, creating a more pleasant working environment.</li>
<li><strong>Enhanced Durability:</strong> SSDs are more resistant to physical shocks, making them ideal for mobile devices.</li>
</ul>
<p class="mb-4">Upgrading to an SSD is a simple yet effective way to breathe new life into your existing hardware. Whether you're a business looking to enhance employee productivity or an individual seeking a faster, more reliable computer, Bay Area Affiliates, Inc. is here to assist you every step of the way.</p>
<p class="mb-4">Contact us today to schedule your HDD to SSD upgrade and experience the difference firsthand!</p>
<a href="#contact" class="text-blue-600 hover:underline"> Get in Touch with Us</a>
<div>
<section>
`
},
'2': {
title: 'Secure Your Corporate Network Access with WireGuard VPN',
image: 'assets/vpn.webp', // Ensure this image exists in your assets folder
content: `
<section class="py-20 bg-white" data-aos="fade-up">
<div class="container mx-auto px-6">
<h2 class="text-3xl font-bold text-center mb-6">Secure Your Corporate Network Access with WireGuard VPN</h2>
<p>
The safest way to access an internal corporate network is through a Virtual Private Network (VPN). A VPN ensures that all actions performed externally mirror those possible within the corporate network, such as accessing Network Attached Storage (NAS) or remotely accessing a desktop via Remote Desktop Protocol (RDP).
</p>
<p class="mb-4">
Let's explore how leveraging a robust VPN solution can enhance your network security.
</p>
<h3 class="text-2xl font-semibold mb-2">Why Choose WireGuard for Your VPN Needs</h3>
<p>
At Bayarea Affiliates, we exclusively use WireGuard, a lightweight VPN variant known for its simplicity and cost-effectiveness. Despite its lightweight nature, WireGuard does not compromise on security, standing toe-to-toe with established alternatives like IPsec and OpenVPN.
</p>
<p class="mb-4">
Understanding the security mechanisms of WireGuard is crucial to appreciating its efficacy.
</p>
<h3 class="text-2xl font-semibold mb-2">Security Mechanisms of WireGuard</h3>
<p>
WireGuard employs state-of-the-art cryptography to ensure secure communications. It uses the Noise Protocol Framework, which provides robust security features such as perfect forward secrecy and authenticated encryption. WireGuard's minimal codebase reduces the potential for vulnerabilities, making it easier to audit and maintain.
</p>
<p class="mb-4">
Now, let's delve into the different implementation options we offer for integrating WireGuard into your network.
</p>
<h3 class="text-2xl font-semibold mb-2">Our WireGuard Implementation Options</h3>
<p>
We support three variants of WireGuard implementation to cater to your specific network setup:
</p>
<ol class="list-decimal list-inside text-gray-700 mb-4">
<li>
<strong>Your Router is WireGuard Capable:</strong> If your current router supports WireGuard (common in some Asus and TP-Link models), we configure it accordingly and provide detailed instructions on its usage. This option is seamless and cost-effective, utilizing your existing hardware.
</li>
<li>
<strong>Upgrade to a WireGuard Capable Router:</strong> If your router does not support WireGuard, we assist you in selecting a compatible router (available from approximately $100, depending on features). We handle the configuration and set up the new router to function analogously to your previous one, ensuring a smooth transition.
</li>
<li>
<strong>Use a Mini PC for WireGuard Integration:</strong> For those who prefer to retain their existing non-WireGuard capable router, we offer an alternative solution. We set up a compact mini PC (currently around $80) that manages the secure connection handshake in tandem with your existing router. While this configuration is more involved and time-consuming, it maintains robust security without compromising your current setup.
</li>
</ol>
<p class="mb-4">
Each implementation option is designed to provide maximum security and flexibility based on your network requirements.
</p>
<h3 class="text-2xl font-semibold mb-2">Ensuring 99.999% Security</h3>
<p>
To achieve near-perfect security, we emphasize attention to critical configuration points. This includes proper key management, regular software updates, and strict access controls. Our comprehensive approach ensures that your VPN setup is resilient against potential threats.
</p>
<p class="mb-4">
Let's recap the benefits and next steps for securing your corporate network with WireGuard VPN.
</p>
<h3 class="text-2xl font-semibold mb-2">Benefits of Implementing WireGuard VPN</h3>
<ul class="list-disc list-inside text-gray-700 mb-4">
<li><strong>Enhanced Security:</strong> Advanced cryptographic techniques protect your data.</li>
<li><strong>Cost-Effective:</strong> Lower setup and maintenance costs compared to other VPN solutions.</li>
<li><strong>Ease of Use:</strong> Simplified configuration process reduces deployment time.</li>
<li><strong>Performance:</strong> High-speed connections with minimal latency.</li>
</ul>
<p class="mb-4">
Ready to secure your corporate network? Contact us today to discuss the best WireGuard implementation strategy for your business.
</p>
<a href="#contact" class="text-blue-600 hover:underline"> Get in Touch with Us</a>
</div>
</section>
`
},
'3': {
title: 'Virtualizing Windows Machines: Future-Proof Your Corporate Network',
image: 'assets/virtualization-windows.webp', // Ensure this image exists in your assets folder
content: `
<section class="py-20 bg-white" data-aos="fade-up">
<div class="container mx-auto px-6">
<h2 class="text-3xl font-bold text-center mb-6">Virtualizing Windows Machines: Future-Proof Your Corporate Network</h2>
<p class="mb-4">
In October 2025, Microsoft will end support for security fixes on Windows 10. To protect your corporate network from hacker attacks post-support, it is essential to upgrade all network computers to Windows 11 or alternative operating systems like macOS or Linux.
</p>
<p class="mb-4">
Upgrading to Windows 11 is straightforward for machines equipped with at least Intel processors from the 8th generation and AMD Ryzen processors from the 3rd generation, without incurring additional licensing costs.
</p>
<h3 class="text-2xl font-semibold mb-2">Seamless Upgrades with Compatible Hardware</h3>
<p class="mb-4">
At Bay Area Affiliates, we are dedicated to making your upgrade process as simple and swift as possible. Whether you're upgrading existing hardware or transitioning to a new operating system, our team ensures minimal disruption to your business operations.
</p>
<p class="mb-4">
For systems running on older hardware, upgrading to new computers becomes a necessity. Bay Area Affiliates assists in procuring either new or refurbished PCs that meet your specific requirements, ensuring a smooth transition by setting them up with your existing software and data.
</p>
<h3 class="text-2xl font-semibold mb-2">Virtualized Windows Machines: A Cost-Effective Alternative</h3>
<p class="mb-4">
An intriguing alternative to investing in new or refurbished PCs is the virtualization of Windows machines. In this setup, your existing PC functions as a thin client, allowing you to remotely access a virtual machine hosted on a server.
</p>
<p class="mb-4">
This approach can be cost-effective since servers capable of hosting 4-5 virtual machines are available for around $1000, translating to approximately $200-250 per computer.
</p>
<h3 class="text-2xl font-semibold mb-2">Efficient Remote Access with RDP</h3>
<p class="mb-4">
Access to these virtual machines is facilitated through RDP (Remote Desktop Protocol), a Microsoft remote protocol extensively utilized in large enterprises. This ensures a reliable and familiar experience for users accessing their virtual desktops.
</p>
<p class="mb-4">
This virtualization strategy is particularly effective for roles primarily involving office tasks. However, it may not be suitable for resource-intensive activities such as video editing.
</p>
<h3 class="text-2xl font-semibold mb-2">Network Requirements for Virtualization</h3>
<p class="mb-4">
A robust and fast network is a prerequisite for effective virtualization. Wired networks are preferred due to their low latency, but a high-quality wireless connection (minimum AC or AX standard) can also suffice for accessing the server.
</p>
<p class="mb-4">
At Bay Area Affiliates, we assist in setting up such virtualization solutions and evaluate whether this approach aligns with your business needs during our consultations.
</p>
<h3 class="text-2xl font-semibold mb-2">Advantages of Virtualization Over Individual PCs</h3>
<p class="mb-4">
Beyond cost savings, virtualization offers numerous advantages over maintaining individual PCs:
</p>
<ul class="list-disc list-inside text-gray-700 mb-4">
<li><strong>Centralized Management:</strong> Manage all virtual machines from a single server, simplifying updates and maintenance.</li>
<li><strong>Scalability:</strong> Easily add or remove virtual machines as your business needs evolve without significant hardware investments.</li>
<li><strong>Enhanced Security:</strong> Implement uniform security policies and quick recovery solutions to protect against threats.</li>
<li><strong>Energy Efficiency:</strong> Reduce overall power consumption by consolidating computing resources.</li>
<li><strong>Disaster Recovery:</strong> Virtual machines can be quickly backed up and restored, minimizing downtime in case of hardware failures.</li>
</ul>
<p class="mb-4">
By leveraging virtualization, businesses can achieve greater flexibility, improved security, and operational efficiencies, ensuring that your corporate network remains robust and adaptable to future challenges.
</p>
<a href="#contact" class="text-blue-600 hover:underline"> Get in Touch with Us</a>
</div>
</section>
`
}
};
constructor() { }
getAllPosts() {
return this.blogPosts;
}
getPost(id: string | null) {
return this.blogPosts[id || '1'];
}
}

BIN
src/assets/hdd2ssd.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 419 KiB

BIN
src/assets/hdd2ssd1.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 581 KiB

BIN
src/assets/it-services.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 378 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 627 KiB

BIN
src/assets/vpn.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 647 KiB

View File

@ -1,13 +1,14 @@
<!doctype html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<title>BayAreaAffiliates</title> <title>Bay Area Affiliates, Inc. | IT Services for Coastal Bend</title>
<base href="/"> <base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico"> <link rel="icon" type="image/x-icon" href="favicon.ico">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
</head> </head>
<body> <body class="font-sans antialiased text-gray-800">
<app-root></app-root> <app-root></app-root>
</body> </body>
</html> </html>

View File

@ -1 +1,4 @@
/* You can add global styles to this file, and also import other style files */ /* You can add global styles to this file, and also import other style files */
@tailwind base;
@tailwind components;
@tailwind utilities;

41
tailwind.config.js Normal file
View File

@ -0,0 +1,41 @@
/** @type {import('tailwindcss').Config} */
module.exports = {
content: [
"./src/**/*.{html,ts}",
"./src/app/services/blog.service.ts", // Include the BlogService explicitly
],
safelist: [
'mb-4',
'text-gray-700',
'text-blue-600',
'hover:underline',
'text-2xl',
'font-semibold',
'list-disc',
'list-inside',
'rounded-lg',
'shadow-lg',
'w-full',
'h-auto',
'object-cover',
'py-20',
'bg-white',
'container',
'mx-auto',
'px-6',
'text-3xl',
'font-bold',
'text-center',
'mb-6',
'text-gray-500',
'text-sm',
'hidden',
'bg-gray-700',
'flex',
// Include any other classes used in dynamic content
],
theme: {
extend: {},
},
plugins: [],
}

View File

@ -4,7 +4,7 @@
"compileOnSave": false, "compileOnSave": false,
"compilerOptions": { "compilerOptions": {
"outDir": "./dist/out-tsc", "outDir": "./dist/out-tsc",
"strict": true, "strict": false,
"noImplicitOverride": true, "noImplicitOverride": true,
"noPropertyAccessFromIndexSignature": true, "noPropertyAccessFromIndexSignature": true,
"noImplicitReturns": true, "noImplicitReturns": true,