@scalemule/news-publication 0.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +74 -0
- package/cookie-consent.css +419 -0
- package/dist/chunk-C7JTEHTH.js +158 -0
- package/dist/chunk-GB36YM56.js +72 -0
- package/dist/chunk-PYCU2T5O.js +93 -0
- package/dist/chunk-R33MJWND.js +261 -0
- package/dist/chunk-TJ7RL3PV.js +252 -0
- package/dist/chunk-YQXS2KQI.js +112 -0
- package/dist/cookie-consent-banner.cjs +210 -0
- package/dist/cookie-consent-banner.d.cts +19 -0
- package/dist/cookie-consent-banner.d.ts +19 -0
- package/dist/cookie-consent-banner.js +3 -0
- package/dist/cookie-settings-view.cjs +470 -0
- package/dist/cookie-settings-view.d.cts +15 -0
- package/dist/cookie-settings-view.d.ts +15 -0
- package/dist/cookie-settings-view.js +3 -0
- package/dist/index.cjs +1460 -0
- package/dist/index.d.cts +317 -0
- package/dist/index.d.ts +317 -0
- package/dist/index.js +441 -0
- package/dist/marketplace-Ch7mdJZv.d.cts +123 -0
- package/dist/marketplace-Ch7mdJZv.d.ts +123 -0
- package/dist/marketplace-forms.cjs +134 -0
- package/dist/marketplace-forms.d.cts +10 -0
- package/dist/marketplace-forms.d.ts +10 -0
- package/dist/marketplace-forms.js +115 -0
- package/dist/marketplace-view.cjs +110 -0
- package/dist/marketplace-view.d.cts +21 -0
- package/dist/marketplace-view.d.ts +21 -0
- package/dist/marketplace-view.js +85 -0
- package/dist/meet-5Ym5bxfh.d.cts +79 -0
- package/dist/meet-5Ym5bxfh.d.ts +79 -0
- package/dist/meet-forms.cjs +188 -0
- package/dist/meet-forms.d.cts +13 -0
- package/dist/meet-forms.d.ts +13 -0
- package/dist/meet-forms.js +166 -0
- package/dist/meet-view.cjs +82 -0
- package/dist/meet-view.d.cts +23 -0
- package/dist/meet-view.d.ts +23 -0
- package/dist/meet-view.js +59 -0
- package/dist/snapshot-BS4hn1dk.d.cts +234 -0
- package/dist/snapshot-BS4hn1dk.d.ts +234 -0
- package/dist/snapshot-file.cjs +192 -0
- package/dist/snapshot-file.d.cts +21 -0
- package/dist/snapshot-file.d.ts +21 -0
- package/dist/snapshot-file.js +38 -0
- package/marketplace.css +61 -0
- package/package.json +103 -0
- package/tokens/broadsheet.css +61 -0
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
var react = require('react');
|
|
5
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
6
|
+
|
|
7
|
+
// src/marketplace-forms.tsx
|
|
8
|
+
|
|
9
|
+
// src/marketplace.ts
|
|
10
|
+
var JOB_EMPLOYMENT_TYPES = [
|
|
11
|
+
{ value: "full_time", label: "Full-time" },
|
|
12
|
+
{ value: "part_time", label: "Part-time" },
|
|
13
|
+
{ value: "contract", label: "Contract" },
|
|
14
|
+
{ value: "temporary", label: "Temporary" },
|
|
15
|
+
{ value: "internship", label: "Internship" }
|
|
16
|
+
];
|
|
17
|
+
var CLASSIFIED_CATEGORIES = [
|
|
18
|
+
{ value: "for-sale", label: "For sale" },
|
|
19
|
+
{ value: "services", label: "Services" },
|
|
20
|
+
{ value: "housing", label: "Housing" },
|
|
21
|
+
{ value: "community", label: "Community" },
|
|
22
|
+
{ value: "wanted", label: "Wanted" }
|
|
23
|
+
];
|
|
24
|
+
function usePost(url, next) {
|
|
25
|
+
const [busy, setBusy] = react.useState(false);
|
|
26
|
+
const [error, setError] = react.useState("");
|
|
27
|
+
const [payload, setPayload] = react.useState(null);
|
|
28
|
+
async function submit(event) {
|
|
29
|
+
event.preventDefault();
|
|
30
|
+
setBusy(true);
|
|
31
|
+
setError("");
|
|
32
|
+
const form = event.currentTarget;
|
|
33
|
+
const data = {};
|
|
34
|
+
new FormData(form).forEach((value, key) => {
|
|
35
|
+
if (typeof value === "string") data[key] = value;
|
|
36
|
+
});
|
|
37
|
+
try {
|
|
38
|
+
const response = await fetch(url, {
|
|
39
|
+
method: "POST",
|
|
40
|
+
headers: { "content-type": "application/json" },
|
|
41
|
+
credentials: "same-origin",
|
|
42
|
+
body: JSON.stringify(data)
|
|
43
|
+
});
|
|
44
|
+
const body = await response.json().catch(() => ({}));
|
|
45
|
+
if (response.status === 401) {
|
|
46
|
+
window.location.assign(`/account?next=${encodeURIComponent(next)}`);
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
if (!response.ok) throw new Error(typeof body.error === "string" ? body.error : "Please try again.");
|
|
50
|
+
setPayload(body);
|
|
51
|
+
form.reset();
|
|
52
|
+
} catch (err) {
|
|
53
|
+
setError(err instanceof Error ? err.message : "Please try again.");
|
|
54
|
+
} finally {
|
|
55
|
+
setBusy(false);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return { busy, error, payload, submit };
|
|
59
|
+
}
|
|
60
|
+
function JobPostForm({ towns }) {
|
|
61
|
+
const post = usePost("/api/jobs", "/jobs/post");
|
|
62
|
+
if (post.payload?.published === true) return /* @__PURE__ */ jsxRuntime.jsx("p", { role: "status", children: "Your job is on the board. Neighbors can find it on the jobs page." });
|
|
63
|
+
if (post.payload) return /* @__PURE__ */ jsxRuntime.jsx("p", { role: "status", children: "Thanks. We saved your job for the newsroom to review and publish." });
|
|
64
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("form", { className: "np-market form", onSubmit: post.submit, children: [
|
|
65
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
|
|
66
|
+
"Job title",
|
|
67
|
+
/* @__PURE__ */ jsxRuntime.jsx("input", { name: "title", required: true, maxLength: 120 })
|
|
68
|
+
] }),
|
|
69
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
|
|
70
|
+
"Employer",
|
|
71
|
+
/* @__PURE__ */ jsxRuntime.jsx("input", { name: "company", required: true, maxLength: 120 })
|
|
72
|
+
] }),
|
|
73
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
|
|
74
|
+
"Town",
|
|
75
|
+
/* @__PURE__ */ jsxRuntime.jsxs("select", { name: "town", required: true, defaultValue: "", children: [
|
|
76
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "", disabled: true, children: "Choose a town" }),
|
|
77
|
+
towns.map((town) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: town, children: town }, town))
|
|
78
|
+
] })
|
|
79
|
+
] }),
|
|
80
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
|
|
81
|
+
"Type",
|
|
82
|
+
/* @__PURE__ */ jsxRuntime.jsx("select", { name: "employment_type", required: true, defaultValue: "full_time", children: JOB_EMPLOYMENT_TYPES.map((item) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: item.value, children: item.label }, item.value)) })
|
|
83
|
+
] }),
|
|
84
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
|
|
85
|
+
"Description",
|
|
86
|
+
/* @__PURE__ */ jsxRuntime.jsx("textarea", { name: "description", required: true, minLength: 20, maxLength: 4e3, rows: 8 })
|
|
87
|
+
] }),
|
|
88
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
|
|
89
|
+
"Apply email",
|
|
90
|
+
/* @__PURE__ */ jsxRuntime.jsx("input", { name: "apply_email", type: "email", maxLength: 254 })
|
|
91
|
+
] }),
|
|
92
|
+
post.error && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "error", role: "alert", children: post.error }),
|
|
93
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { className: "primary", disabled: post.busy, children: post.busy ? "Saving\u2026" : "Post job" })
|
|
94
|
+
] });
|
|
95
|
+
}
|
|
96
|
+
function ClassifiedPostForm({ towns }) {
|
|
97
|
+
const post = usePost("/api/classifieds", "/classifieds/post");
|
|
98
|
+
const id = typeof post.payload?.id === "string" ? post.payload.id : "";
|
|
99
|
+
if (id) return /* @__PURE__ */ jsxRuntime.jsxs("p", { role: "status", children: [
|
|
100
|
+
"Your listing is up. ",
|
|
101
|
+
/* @__PURE__ */ jsxRuntime.jsx("a", { href: `/classifieds/${encodeURIComponent(id)}`, children: "View it" }),
|
|
102
|
+
"."
|
|
103
|
+
] });
|
|
104
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("form", { className: "np-market form", onSubmit: post.submit, children: [
|
|
105
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
|
|
106
|
+
"Title",
|
|
107
|
+
/* @__PURE__ */ jsxRuntime.jsx("input", { name: "title", required: true, maxLength: 120 })
|
|
108
|
+
] }),
|
|
109
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
|
|
110
|
+
"Category",
|
|
111
|
+
/* @__PURE__ */ jsxRuntime.jsx("select", { name: "category", required: true, defaultValue: "for-sale", children: CLASSIFIED_CATEGORIES.map((item) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: item.value, children: item.label }, item.value)) })
|
|
112
|
+
] }),
|
|
113
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
|
|
114
|
+
"Town",
|
|
115
|
+
/* @__PURE__ */ jsxRuntime.jsxs("select", { name: "town", required: true, defaultValue: "", children: [
|
|
116
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "", disabled: true, children: "Choose a town" }),
|
|
117
|
+
towns.map((town) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: town, children: town }, town))
|
|
118
|
+
] })
|
|
119
|
+
] }),
|
|
120
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
|
|
121
|
+
"Price, optional",
|
|
122
|
+
/* @__PURE__ */ jsxRuntime.jsx("input", { name: "price", type: "number", min: "0", step: "1" })
|
|
123
|
+
] }),
|
|
124
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
|
|
125
|
+
"Description",
|
|
126
|
+
/* @__PURE__ */ jsxRuntime.jsx("textarea", { name: "description", required: true, minLength: 20, maxLength: 4e3, rows: 8 })
|
|
127
|
+
] }),
|
|
128
|
+
post.error && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "error", role: "alert", children: post.error }),
|
|
129
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { className: "primary", disabled: post.busy, children: post.busy ? "Saving\u2026" : "Place listing" })
|
|
130
|
+
] });
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
exports.ClassifiedPostForm = ClassifiedPostForm;
|
|
134
|
+
exports.JobPostForm = JobPostForm;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
|
|
3
|
+
declare function JobPostForm({ towns }: {
|
|
4
|
+
towns: string[];
|
|
5
|
+
}): react.JSX.Element;
|
|
6
|
+
declare function ClassifiedPostForm({ towns }: {
|
|
7
|
+
towns: string[];
|
|
8
|
+
}): react.JSX.Element;
|
|
9
|
+
|
|
10
|
+
export { ClassifiedPostForm, JobPostForm };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
|
|
3
|
+
declare function JobPostForm({ towns }: {
|
|
4
|
+
towns: string[];
|
|
5
|
+
}): react.JSX.Element;
|
|
6
|
+
declare function ClassifiedPostForm({ towns }: {
|
|
7
|
+
towns: string[];
|
|
8
|
+
}): react.JSX.Element;
|
|
9
|
+
|
|
10
|
+
export { ClassifiedPostForm, JobPostForm };
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { JOB_EMPLOYMENT_TYPES, CLASSIFIED_CATEGORIES } from './chunk-YQXS2KQI.js';
|
|
3
|
+
import { useState } from 'react';
|
|
4
|
+
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
5
|
+
|
|
6
|
+
function usePost(url, next) {
|
|
7
|
+
const [busy, setBusy] = useState(false);
|
|
8
|
+
const [error, setError] = useState("");
|
|
9
|
+
const [payload, setPayload] = useState(null);
|
|
10
|
+
async function submit(event) {
|
|
11
|
+
event.preventDefault();
|
|
12
|
+
setBusy(true);
|
|
13
|
+
setError("");
|
|
14
|
+
const form = event.currentTarget;
|
|
15
|
+
const data = {};
|
|
16
|
+
new FormData(form).forEach((value, key) => {
|
|
17
|
+
if (typeof value === "string") data[key] = value;
|
|
18
|
+
});
|
|
19
|
+
try {
|
|
20
|
+
const response = await fetch(url, {
|
|
21
|
+
method: "POST",
|
|
22
|
+
headers: { "content-type": "application/json" },
|
|
23
|
+
credentials: "same-origin",
|
|
24
|
+
body: JSON.stringify(data)
|
|
25
|
+
});
|
|
26
|
+
const body = await response.json().catch(() => ({}));
|
|
27
|
+
if (response.status === 401) {
|
|
28
|
+
window.location.assign(`/account?next=${encodeURIComponent(next)}`);
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
if (!response.ok) throw new Error(typeof body.error === "string" ? body.error : "Please try again.");
|
|
32
|
+
setPayload(body);
|
|
33
|
+
form.reset();
|
|
34
|
+
} catch (err) {
|
|
35
|
+
setError(err instanceof Error ? err.message : "Please try again.");
|
|
36
|
+
} finally {
|
|
37
|
+
setBusy(false);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return { busy, error, payload, submit };
|
|
41
|
+
}
|
|
42
|
+
function JobPostForm({ towns }) {
|
|
43
|
+
const post = usePost("/api/jobs", "/jobs/post");
|
|
44
|
+
if (post.payload?.published === true) return /* @__PURE__ */ jsx("p", { role: "status", children: "Your job is on the board. Neighbors can find it on the jobs page." });
|
|
45
|
+
if (post.payload) return /* @__PURE__ */ jsx("p", { role: "status", children: "Thanks. We saved your job for the newsroom to review and publish." });
|
|
46
|
+
return /* @__PURE__ */ jsxs("form", { className: "np-market form", onSubmit: post.submit, children: [
|
|
47
|
+
/* @__PURE__ */ jsxs("label", { children: [
|
|
48
|
+
"Job title",
|
|
49
|
+
/* @__PURE__ */ jsx("input", { name: "title", required: true, maxLength: 120 })
|
|
50
|
+
] }),
|
|
51
|
+
/* @__PURE__ */ jsxs("label", { children: [
|
|
52
|
+
"Employer",
|
|
53
|
+
/* @__PURE__ */ jsx("input", { name: "company", required: true, maxLength: 120 })
|
|
54
|
+
] }),
|
|
55
|
+
/* @__PURE__ */ jsxs("label", { children: [
|
|
56
|
+
"Town",
|
|
57
|
+
/* @__PURE__ */ jsxs("select", { name: "town", required: true, defaultValue: "", children: [
|
|
58
|
+
/* @__PURE__ */ jsx("option", { value: "", disabled: true, children: "Choose a town" }),
|
|
59
|
+
towns.map((town) => /* @__PURE__ */ jsx("option", { value: town, children: town }, town))
|
|
60
|
+
] })
|
|
61
|
+
] }),
|
|
62
|
+
/* @__PURE__ */ jsxs("label", { children: [
|
|
63
|
+
"Type",
|
|
64
|
+
/* @__PURE__ */ jsx("select", { name: "employment_type", required: true, defaultValue: "full_time", children: JOB_EMPLOYMENT_TYPES.map((item) => /* @__PURE__ */ jsx("option", { value: item.value, children: item.label }, item.value)) })
|
|
65
|
+
] }),
|
|
66
|
+
/* @__PURE__ */ jsxs("label", { children: [
|
|
67
|
+
"Description",
|
|
68
|
+
/* @__PURE__ */ jsx("textarea", { name: "description", required: true, minLength: 20, maxLength: 4e3, rows: 8 })
|
|
69
|
+
] }),
|
|
70
|
+
/* @__PURE__ */ jsxs("label", { children: [
|
|
71
|
+
"Apply email",
|
|
72
|
+
/* @__PURE__ */ jsx("input", { name: "apply_email", type: "email", maxLength: 254 })
|
|
73
|
+
] }),
|
|
74
|
+
post.error && /* @__PURE__ */ jsx("p", { className: "error", role: "alert", children: post.error }),
|
|
75
|
+
/* @__PURE__ */ jsx("button", { className: "primary", disabled: post.busy, children: post.busy ? "Saving\u2026" : "Post job" })
|
|
76
|
+
] });
|
|
77
|
+
}
|
|
78
|
+
function ClassifiedPostForm({ towns }) {
|
|
79
|
+
const post = usePost("/api/classifieds", "/classifieds/post");
|
|
80
|
+
const id = typeof post.payload?.id === "string" ? post.payload.id : "";
|
|
81
|
+
if (id) return /* @__PURE__ */ jsxs("p", { role: "status", children: [
|
|
82
|
+
"Your listing is up. ",
|
|
83
|
+
/* @__PURE__ */ jsx("a", { href: `/classifieds/${encodeURIComponent(id)}`, children: "View it" }),
|
|
84
|
+
"."
|
|
85
|
+
] });
|
|
86
|
+
return /* @__PURE__ */ jsxs("form", { className: "np-market form", onSubmit: post.submit, children: [
|
|
87
|
+
/* @__PURE__ */ jsxs("label", { children: [
|
|
88
|
+
"Title",
|
|
89
|
+
/* @__PURE__ */ jsx("input", { name: "title", required: true, maxLength: 120 })
|
|
90
|
+
] }),
|
|
91
|
+
/* @__PURE__ */ jsxs("label", { children: [
|
|
92
|
+
"Category",
|
|
93
|
+
/* @__PURE__ */ jsx("select", { name: "category", required: true, defaultValue: "for-sale", children: CLASSIFIED_CATEGORIES.map((item) => /* @__PURE__ */ jsx("option", { value: item.value, children: item.label }, item.value)) })
|
|
94
|
+
] }),
|
|
95
|
+
/* @__PURE__ */ jsxs("label", { children: [
|
|
96
|
+
"Town",
|
|
97
|
+
/* @__PURE__ */ jsxs("select", { name: "town", required: true, defaultValue: "", children: [
|
|
98
|
+
/* @__PURE__ */ jsx("option", { value: "", disabled: true, children: "Choose a town" }),
|
|
99
|
+
towns.map((town) => /* @__PURE__ */ jsx("option", { value: town, children: town }, town))
|
|
100
|
+
] })
|
|
101
|
+
] }),
|
|
102
|
+
/* @__PURE__ */ jsxs("label", { children: [
|
|
103
|
+
"Price, optional",
|
|
104
|
+
/* @__PURE__ */ jsx("input", { name: "price", type: "number", min: "0", step: "1" })
|
|
105
|
+
] }),
|
|
106
|
+
/* @__PURE__ */ jsxs("label", { children: [
|
|
107
|
+
"Description",
|
|
108
|
+
/* @__PURE__ */ jsx("textarea", { name: "description", required: true, minLength: 20, maxLength: 4e3, rows: 8 })
|
|
109
|
+
] }),
|
|
110
|
+
post.error && /* @__PURE__ */ jsx("p", { className: "error", role: "alert", children: post.error }),
|
|
111
|
+
/* @__PURE__ */ jsx("button", { className: "primary", disabled: post.busy, children: post.busy ? "Saving\u2026" : "Place listing" })
|
|
112
|
+
] });
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
export { ClassifiedPostForm, JobPostForm };
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
4
|
+
|
|
5
|
+
// src/marketplace.ts
|
|
6
|
+
var JOB_EMPLOYMENT_TYPES = [
|
|
7
|
+
{ value: "full_time", label: "Full-time" },
|
|
8
|
+
{ value: "part_time", label: "Part-time" },
|
|
9
|
+
{ value: "contract", label: "Contract" },
|
|
10
|
+
{ value: "temporary", label: "Temporary" },
|
|
11
|
+
{ value: "internship", label: "Internship" }
|
|
12
|
+
];
|
|
13
|
+
var CLASSIFIED_CATEGORIES = [
|
|
14
|
+
{ value: "for-sale", label: "For sale" },
|
|
15
|
+
{ value: "services", label: "Services" },
|
|
16
|
+
{ value: "housing", label: "Housing" },
|
|
17
|
+
{ value: "community", label: "Community" },
|
|
18
|
+
{ value: "wanted", label: "Wanted" }
|
|
19
|
+
];
|
|
20
|
+
function employmentLabel(value) {
|
|
21
|
+
return JOB_EMPLOYMENT_TYPES.find((item) => item.value === value)?.label ?? "";
|
|
22
|
+
}
|
|
23
|
+
function categoryLabel(value) {
|
|
24
|
+
return CLASSIFIED_CATEGORIES.find((item) => item.value === value)?.label ?? "";
|
|
25
|
+
}
|
|
26
|
+
function money(price) {
|
|
27
|
+
return price != null ? `$${price}` : null;
|
|
28
|
+
}
|
|
29
|
+
function JobsBoard({ region, jobs, query }) {
|
|
30
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "np-market", children: [
|
|
31
|
+
/* @__PURE__ */ jsxRuntime.jsx("h1", { children: "Jobs" }),
|
|
32
|
+
/* @__PURE__ */ jsxRuntime.jsxs("p", { className: "lead", children: [
|
|
33
|
+
"Local openings from ",
|
|
34
|
+
region,
|
|
35
|
+
" employers. Browse free. Post a job without a credit card."
|
|
36
|
+
] }),
|
|
37
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "actions", children: [
|
|
38
|
+
/* @__PURE__ */ jsxRuntime.jsx("a", { className: "primary", href: "/jobs/post", children: "Post a job" }),
|
|
39
|
+
/* @__PURE__ */ jsxRuntime.jsx("a", { className: "secondary", href: "/classifieds", children: "Classifieds" })
|
|
40
|
+
] }),
|
|
41
|
+
/* @__PURE__ */ jsxRuntime.jsxs("form", { className: "search", method: "get", action: "/jobs", children: [
|
|
42
|
+
/* @__PURE__ */ jsxRuntime.jsx("input", { name: "q", defaultValue: query, "aria-label": "Search jobs", placeholder: "Title or employer", maxLength: 80 }),
|
|
43
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { className: "secondary", type: "submit", children: "Search" })
|
|
44
|
+
] }),
|
|
45
|
+
jobs.length === 0 ? /* @__PURE__ */ jsxRuntime.jsxs("section", { className: "empty", children: [
|
|
46
|
+
/* @__PURE__ */ jsxRuntime.jsx("h2", { children: "No live jobs yet." }),
|
|
47
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { children: "Be the first local employer on the board." })
|
|
48
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "list", children: jobs.map((job) => /* @__PURE__ */ jsxRuntime.jsxs("a", { className: "item", href: `/jobs/${encodeURIComponent(job.slug)}`, children: [
|
|
49
|
+
/* @__PURE__ */ jsxRuntime.jsx("h2", { children: job.title }),
|
|
50
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "meta", children: [employmentLabel(job.employment_type), job.location_type === "remote" || job.remote_allowed ? "Remote" : "On-site"].filter(Boolean).join(" \xB7 ") })
|
|
51
|
+
] }, job.id)) })
|
|
52
|
+
] });
|
|
53
|
+
}
|
|
54
|
+
function JobArticle({ job }) {
|
|
55
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("article", { className: "np-market", children: [
|
|
56
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "meta", children: /* @__PURE__ */ jsxRuntime.jsx("a", { href: "/jobs", children: "Jobs" }) }),
|
|
57
|
+
/* @__PURE__ */ jsxRuntime.jsx("h1", { children: job.title }),
|
|
58
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "body", children: job.body_md || "Details are in the listing." }),
|
|
59
|
+
/* @__PURE__ */ jsxRuntime.jsxs("p", { className: "actions", children: [
|
|
60
|
+
/* @__PURE__ */ jsxRuntime.jsx("a", { className: "secondary", href: "/jobs", children: "All jobs" }),
|
|
61
|
+
/* @__PURE__ */ jsxRuntime.jsx("a", { className: "primary", href: "/jobs/post", children: "Post a job" })
|
|
62
|
+
] })
|
|
63
|
+
] });
|
|
64
|
+
}
|
|
65
|
+
function ClassifiedsBoard({
|
|
66
|
+
region,
|
|
67
|
+
listings,
|
|
68
|
+
category
|
|
69
|
+
}) {
|
|
70
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "np-market", children: [
|
|
71
|
+
/* @__PURE__ */ jsxRuntime.jsx("h1", { children: "Classifieds" }),
|
|
72
|
+
/* @__PURE__ */ jsxRuntime.jsxs("p", { className: "lead", children: [
|
|
73
|
+
"For sale, services, housing and community notices from ",
|
|
74
|
+
region,
|
|
75
|
+
". Listings stay up for 30 days."
|
|
76
|
+
] }),
|
|
77
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "actions", children: [
|
|
78
|
+
/* @__PURE__ */ jsxRuntime.jsx("a", { className: "primary", href: "/classifieds/post", children: "Place a listing" }),
|
|
79
|
+
/* @__PURE__ */ jsxRuntime.jsx("a", { className: "secondary", href: "/jobs", children: "Jobs" })
|
|
80
|
+
] }),
|
|
81
|
+
/* @__PURE__ */ jsxRuntime.jsxs("nav", { className: "filter", "aria-label": "Categories", children: [
|
|
82
|
+
/* @__PURE__ */ jsxRuntime.jsx("a", { className: !category ? "on" : void 0, href: "/classifieds", children: "All" }),
|
|
83
|
+
CLASSIFIED_CATEGORIES.map((item) => /* @__PURE__ */ jsxRuntime.jsx("a", { className: category === item.value ? "on" : void 0, href: `/classifieds?category=${item.value}`, children: item.label }, item.value))
|
|
84
|
+
] }),
|
|
85
|
+
listings.length === 0 ? /* @__PURE__ */ jsxRuntime.jsxs("section", { className: "empty", children: [
|
|
86
|
+
/* @__PURE__ */ jsxRuntime.jsx("h2", { children: "No classifieds yet." }),
|
|
87
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { children: "Post something neighbors might need." })
|
|
88
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "list", children: listings.map((listing) => /* @__PURE__ */ jsxRuntime.jsxs("a", { className: "item", href: `/classifieds/${encodeURIComponent(listing.id)}`, children: [
|
|
89
|
+
/* @__PURE__ */ jsxRuntime.jsx("h2", { children: listing.title }),
|
|
90
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "meta", children: [categoryLabel(listing.category), listing.location?.town, money(listing.price)].filter(Boolean).join(" \xB7 ") })
|
|
91
|
+
] }, listing.id)) })
|
|
92
|
+
] });
|
|
93
|
+
}
|
|
94
|
+
function ClassifiedArticle({ listing }) {
|
|
95
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("article", { className: "np-market", children: [
|
|
96
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "meta", children: /* @__PURE__ */ jsxRuntime.jsx("a", { href: "/classifieds", children: "Classifieds" }) }),
|
|
97
|
+
/* @__PURE__ */ jsxRuntime.jsx("h1", { children: listing.title }),
|
|
98
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "meta", children: [categoryLabel(listing.category), listing.location?.town, money(listing.price)].filter(Boolean).join(" \xB7 ") }),
|
|
99
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "body", children: listing.description }),
|
|
100
|
+
/* @__PURE__ */ jsxRuntime.jsxs("p", { className: "actions", children: [
|
|
101
|
+
/* @__PURE__ */ jsxRuntime.jsx("a", { className: "secondary", href: "/classifieds", children: "All classifieds" }),
|
|
102
|
+
/* @__PURE__ */ jsxRuntime.jsx("a", { className: "primary", href: "/classifieds/post", children: "Place a listing" })
|
|
103
|
+
] })
|
|
104
|
+
] });
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
exports.ClassifiedArticle = ClassifiedArticle;
|
|
108
|
+
exports.ClassifiedsBoard = ClassifiedsBoard;
|
|
109
|
+
exports.JobArticle = JobArticle;
|
|
110
|
+
exports.JobsBoard = JobsBoard;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { b as ClassifiedListing, d as PublicJob } from './marketplace-Ch7mdJZv.cjs';
|
|
3
|
+
|
|
4
|
+
declare function JobsBoard({ region, jobs, query }: {
|
|
5
|
+
region: string;
|
|
6
|
+
jobs: PublicJob[];
|
|
7
|
+
query: string;
|
|
8
|
+
}): react.JSX.Element;
|
|
9
|
+
declare function JobArticle({ job }: {
|
|
10
|
+
job: PublicJob;
|
|
11
|
+
}): react.JSX.Element;
|
|
12
|
+
declare function ClassifiedsBoard({ region, listings, category, }: {
|
|
13
|
+
region: string;
|
|
14
|
+
listings: ClassifiedListing[];
|
|
15
|
+
category: string;
|
|
16
|
+
}): react.JSX.Element;
|
|
17
|
+
declare function ClassifiedArticle({ listing }: {
|
|
18
|
+
listing: ClassifiedListing;
|
|
19
|
+
}): react.JSX.Element;
|
|
20
|
+
|
|
21
|
+
export { ClassifiedArticle, ClassifiedsBoard, JobArticle, JobsBoard };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { b as ClassifiedListing, d as PublicJob } from './marketplace-Ch7mdJZv.js';
|
|
3
|
+
|
|
4
|
+
declare function JobsBoard({ region, jobs, query }: {
|
|
5
|
+
region: string;
|
|
6
|
+
jobs: PublicJob[];
|
|
7
|
+
query: string;
|
|
8
|
+
}): react.JSX.Element;
|
|
9
|
+
declare function JobArticle({ job }: {
|
|
10
|
+
job: PublicJob;
|
|
11
|
+
}): react.JSX.Element;
|
|
12
|
+
declare function ClassifiedsBoard({ region, listings, category, }: {
|
|
13
|
+
region: string;
|
|
14
|
+
listings: ClassifiedListing[];
|
|
15
|
+
category: string;
|
|
16
|
+
}): react.JSX.Element;
|
|
17
|
+
declare function ClassifiedArticle({ listing }: {
|
|
18
|
+
listing: ClassifiedListing;
|
|
19
|
+
}): react.JSX.Element;
|
|
20
|
+
|
|
21
|
+
export { ClassifiedArticle, ClassifiedsBoard, JobArticle, JobsBoard };
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { employmentLabel, CLASSIFIED_CATEGORIES, categoryLabel } from './chunk-YQXS2KQI.js';
|
|
2
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
3
|
+
|
|
4
|
+
function money(price) {
|
|
5
|
+
return price != null ? `$${price}` : null;
|
|
6
|
+
}
|
|
7
|
+
function JobsBoard({ region, jobs, query }) {
|
|
8
|
+
return /* @__PURE__ */ jsxs("div", { className: "np-market", children: [
|
|
9
|
+
/* @__PURE__ */ jsx("h1", { children: "Jobs" }),
|
|
10
|
+
/* @__PURE__ */ jsxs("p", { className: "lead", children: [
|
|
11
|
+
"Local openings from ",
|
|
12
|
+
region,
|
|
13
|
+
" employers. Browse free. Post a job without a credit card."
|
|
14
|
+
] }),
|
|
15
|
+
/* @__PURE__ */ jsxs("div", { className: "actions", children: [
|
|
16
|
+
/* @__PURE__ */ jsx("a", { className: "primary", href: "/jobs/post", children: "Post a job" }),
|
|
17
|
+
/* @__PURE__ */ jsx("a", { className: "secondary", href: "/classifieds", children: "Classifieds" })
|
|
18
|
+
] }),
|
|
19
|
+
/* @__PURE__ */ jsxs("form", { className: "search", method: "get", action: "/jobs", children: [
|
|
20
|
+
/* @__PURE__ */ jsx("input", { name: "q", defaultValue: query, "aria-label": "Search jobs", placeholder: "Title or employer", maxLength: 80 }),
|
|
21
|
+
/* @__PURE__ */ jsx("button", { className: "secondary", type: "submit", children: "Search" })
|
|
22
|
+
] }),
|
|
23
|
+
jobs.length === 0 ? /* @__PURE__ */ jsxs("section", { className: "empty", children: [
|
|
24
|
+
/* @__PURE__ */ jsx("h2", { children: "No live jobs yet." }),
|
|
25
|
+
/* @__PURE__ */ jsx("p", { children: "Be the first local employer on the board." })
|
|
26
|
+
] }) : /* @__PURE__ */ jsx("div", { className: "list", children: jobs.map((job) => /* @__PURE__ */ jsxs("a", { className: "item", href: `/jobs/${encodeURIComponent(job.slug)}`, children: [
|
|
27
|
+
/* @__PURE__ */ jsx("h2", { children: job.title }),
|
|
28
|
+
/* @__PURE__ */ jsx("p", { className: "meta", children: [employmentLabel(job.employment_type), job.location_type === "remote" || job.remote_allowed ? "Remote" : "On-site"].filter(Boolean).join(" \xB7 ") })
|
|
29
|
+
] }, job.id)) })
|
|
30
|
+
] });
|
|
31
|
+
}
|
|
32
|
+
function JobArticle({ job }) {
|
|
33
|
+
return /* @__PURE__ */ jsxs("article", { className: "np-market", children: [
|
|
34
|
+
/* @__PURE__ */ jsx("p", { className: "meta", children: /* @__PURE__ */ jsx("a", { href: "/jobs", children: "Jobs" }) }),
|
|
35
|
+
/* @__PURE__ */ jsx("h1", { children: job.title }),
|
|
36
|
+
/* @__PURE__ */ jsx("div", { className: "body", children: job.body_md || "Details are in the listing." }),
|
|
37
|
+
/* @__PURE__ */ jsxs("p", { className: "actions", children: [
|
|
38
|
+
/* @__PURE__ */ jsx("a", { className: "secondary", href: "/jobs", children: "All jobs" }),
|
|
39
|
+
/* @__PURE__ */ jsx("a", { className: "primary", href: "/jobs/post", children: "Post a job" })
|
|
40
|
+
] })
|
|
41
|
+
] });
|
|
42
|
+
}
|
|
43
|
+
function ClassifiedsBoard({
|
|
44
|
+
region,
|
|
45
|
+
listings,
|
|
46
|
+
category
|
|
47
|
+
}) {
|
|
48
|
+
return /* @__PURE__ */ jsxs("div", { className: "np-market", children: [
|
|
49
|
+
/* @__PURE__ */ jsx("h1", { children: "Classifieds" }),
|
|
50
|
+
/* @__PURE__ */ jsxs("p", { className: "lead", children: [
|
|
51
|
+
"For sale, services, housing and community notices from ",
|
|
52
|
+
region,
|
|
53
|
+
". Listings stay up for 30 days."
|
|
54
|
+
] }),
|
|
55
|
+
/* @__PURE__ */ jsxs("div", { className: "actions", children: [
|
|
56
|
+
/* @__PURE__ */ jsx("a", { className: "primary", href: "/classifieds/post", children: "Place a listing" }),
|
|
57
|
+
/* @__PURE__ */ jsx("a", { className: "secondary", href: "/jobs", children: "Jobs" })
|
|
58
|
+
] }),
|
|
59
|
+
/* @__PURE__ */ jsxs("nav", { className: "filter", "aria-label": "Categories", children: [
|
|
60
|
+
/* @__PURE__ */ jsx("a", { className: !category ? "on" : void 0, href: "/classifieds", children: "All" }),
|
|
61
|
+
CLASSIFIED_CATEGORIES.map((item) => /* @__PURE__ */ jsx("a", { className: category === item.value ? "on" : void 0, href: `/classifieds?category=${item.value}`, children: item.label }, item.value))
|
|
62
|
+
] }),
|
|
63
|
+
listings.length === 0 ? /* @__PURE__ */ jsxs("section", { className: "empty", children: [
|
|
64
|
+
/* @__PURE__ */ jsx("h2", { children: "No classifieds yet." }),
|
|
65
|
+
/* @__PURE__ */ jsx("p", { children: "Post something neighbors might need." })
|
|
66
|
+
] }) : /* @__PURE__ */ jsx("div", { className: "list", children: listings.map((listing) => /* @__PURE__ */ jsxs("a", { className: "item", href: `/classifieds/${encodeURIComponent(listing.id)}`, children: [
|
|
67
|
+
/* @__PURE__ */ jsx("h2", { children: listing.title }),
|
|
68
|
+
/* @__PURE__ */ jsx("p", { className: "meta", children: [categoryLabel(listing.category), listing.location?.town, money(listing.price)].filter(Boolean).join(" \xB7 ") })
|
|
69
|
+
] }, listing.id)) })
|
|
70
|
+
] });
|
|
71
|
+
}
|
|
72
|
+
function ClassifiedArticle({ listing }) {
|
|
73
|
+
return /* @__PURE__ */ jsxs("article", { className: "np-market", children: [
|
|
74
|
+
/* @__PURE__ */ jsx("p", { className: "meta", children: /* @__PURE__ */ jsx("a", { href: "/classifieds", children: "Classifieds" }) }),
|
|
75
|
+
/* @__PURE__ */ jsx("h1", { children: listing.title }),
|
|
76
|
+
/* @__PURE__ */ jsx("p", { className: "meta", children: [categoryLabel(listing.category), listing.location?.town, money(listing.price)].filter(Boolean).join(" \xB7 ") }),
|
|
77
|
+
/* @__PURE__ */ jsx("div", { className: "body", children: listing.description }),
|
|
78
|
+
/* @__PURE__ */ jsxs("p", { className: "actions", children: [
|
|
79
|
+
/* @__PURE__ */ jsx("a", { className: "secondary", href: "/classifieds", children: "All classifieds" }),
|
|
80
|
+
/* @__PURE__ */ jsx("a", { className: "primary", href: "/classifieds/post", children: "Place a listing" })
|
|
81
|
+
] })
|
|
82
|
+
] });
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export { ClassifiedArticle, ClassifiedsBoard, JobArticle, JobsBoard };
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/** Rules for in-person meetups and the paper's chat. */
|
|
2
|
+
declare const MEET_ACTIVITIES: readonly [{
|
|
3
|
+
readonly value: "coffee";
|
|
4
|
+
readonly label: "Coffee";
|
|
5
|
+
}, {
|
|
6
|
+
readonly value: "walk";
|
|
7
|
+
readonly label: "Walk";
|
|
8
|
+
}, {
|
|
9
|
+
readonly value: "hike";
|
|
10
|
+
readonly label: "Hike";
|
|
11
|
+
}, {
|
|
12
|
+
readonly value: "pickleball";
|
|
13
|
+
readonly label: "Pickleball";
|
|
14
|
+
}, {
|
|
15
|
+
readonly value: "tennis";
|
|
16
|
+
readonly label: "Tennis";
|
|
17
|
+
}, {
|
|
18
|
+
readonly value: "soccer";
|
|
19
|
+
readonly label: "Soccer";
|
|
20
|
+
}, {
|
|
21
|
+
readonly value: "bike";
|
|
22
|
+
readonly label: "Bike ride";
|
|
23
|
+
}, {
|
|
24
|
+
readonly value: "dogs";
|
|
25
|
+
readonly label: "Dog walk";
|
|
26
|
+
}, {
|
|
27
|
+
readonly value: "books";
|
|
28
|
+
readonly label: "Book club";
|
|
29
|
+
}, {
|
|
30
|
+
readonly value: "games";
|
|
31
|
+
readonly label: "Board games";
|
|
32
|
+
}, {
|
|
33
|
+
readonly value: "kids";
|
|
34
|
+
readonly label: "Kids outing";
|
|
35
|
+
}, {
|
|
36
|
+
readonly value: "volunteer";
|
|
37
|
+
readonly label: "Volunteer";
|
|
38
|
+
}, {
|
|
39
|
+
readonly value: "other";
|
|
40
|
+
readonly label: "Something else";
|
|
41
|
+
}];
|
|
42
|
+
type MeetActivity = (typeof MEET_ACTIVITIES)[number]["value"];
|
|
43
|
+
type PublicPlace = {
|
|
44
|
+
id: string;
|
|
45
|
+
name: string;
|
|
46
|
+
detail: string;
|
|
47
|
+
};
|
|
48
|
+
type MeetupInput = {
|
|
49
|
+
activity?: unknown;
|
|
50
|
+
otherLabel?: unknown;
|
|
51
|
+
placeId?: unknown;
|
|
52
|
+
startsAt?: unknown;
|
|
53
|
+
notes?: unknown;
|
|
54
|
+
capacity?: unknown;
|
|
55
|
+
};
|
|
56
|
+
type PreparedMeetup = {
|
|
57
|
+
activity: MeetActivity;
|
|
58
|
+
activityLabel: string;
|
|
59
|
+
placeId: string;
|
|
60
|
+
placeName: string;
|
|
61
|
+
placeDetail: string;
|
|
62
|
+
startsAt: string;
|
|
63
|
+
notes: string;
|
|
64
|
+
capacity: number;
|
|
65
|
+
};
|
|
66
|
+
declare function isAdult(bornOn: string, now?: Date): boolean;
|
|
67
|
+
declare function canHostMeetup(accountCreatedAt: string, now?: Date): boolean;
|
|
68
|
+
/** Refuse phone numbers, email addresses, and contact links. */
|
|
69
|
+
declare function screenMessage(value: string): {
|
|
70
|
+
ok: true;
|
|
71
|
+
text: string;
|
|
72
|
+
} | {
|
|
73
|
+
ok: false;
|
|
74
|
+
reason: string;
|
|
75
|
+
};
|
|
76
|
+
declare function activityLabel(value: string, otherLabel?: string): string;
|
|
77
|
+
declare function prepareMeetup(input: MeetupInput, places: PublicPlace[], now?: Date): PreparedMeetup;
|
|
78
|
+
|
|
79
|
+
export { MEET_ACTIVITIES as M, type PreparedMeetup as P, type MeetActivity as a, type MeetupInput as b, type PublicPlace as c, activityLabel as d, canHostMeetup as e, isAdult as i, prepareMeetup as p, screenMessage as s };
|