todos-contra-el-fuego-web/imports/ui/pages/Subscriptions/Subscriptions.js
vjrj 12bdbe8fed deps: i18next 10 -> 23, react-i18next 7 -> 14
Modernizes the whole i18n stack:
- 48 translate([], {wait:true}) / translate() HOCs -> withTranslation()
- react.wait:true -> react.useSuspense:false
- whitelist -> supportedLngs; added compatibilityJSON: 'v3' so our
  natural-language keys + v3 _plural layout keep working (custom
  separators ss/eth/dj preserved)
- backends: xhr -> i18next-http-backend (client), sync-fs ->
  i18next-fs-backend (server); dropped i18next-localstorage-cache
  (was enabled:false); languagedetector 2 -> 8
- ReSendEmail: <Interpolate> (removed in v10) -> <Trans values={{email}}/>,
  dropped the removed bare t export
- saveMissing handler signature (lngs, ns, key, fallbackValue)

Silences the per-component Translate/I18n legacy-context warnings.
Browser-verified es/en switch and <Trans> interpolation on /fires;
REST smoke byte-identical.
2026-07-18 06:28:41 +02:00

138 lines
5 KiB
JavaScript

/* eslint-disable react/jsx-indent-props */
/* eslint-disable import/no-absolute-path */
/* eslint-disable react/jsx-indent */
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { Alert } from 'react-bootstrap';
import { Meteor } from 'meteor/meteor';
import { withTracker } from 'meteor/react-meteor-data';
import { Trans, withTranslation } from 'react-i18next';
import { Bert } from 'meteor/themeteorchef:bert';
import { Helmet } from 'react-helmet-async';
import UserSubsToFiresCollection from '/imports/api/Subscriptions/Subscriptions';
import SelectionMap, { action } from '/imports/ui/components/SelectionMap/SelectionMap';
import confirm from '/imports/ui/components/Prompt/Confirm';
import Loading from '../../components/Loading/Loading';
import './Subscriptions.scss';
class Subscriptions extends Component {
constructor(props) {
super(props);
this.t = props.t;
const received = props.location.state;
if (received && received.location && received.location.lat && received.location.lon && received.distance) {
props.history.push(`${this.props.match.url}/new`, {
location: received.location,
distance: received.distance,
center: [received.location.lat, received.location.lon]
});
}
this.state = {};
this.state.action = action.view;
this.onViewportChanged = this.onViewportChanged.bind(this);
this.onFstBtn = this.onFstBtn.bind(this);
this.onSndBtn = this.onSndBtn.bind(this);
}
onFstBtn() {
// console.log(this.state);
if (this.state.action === action.view) {
this.props.history.push(`${this.props.match.url}/new`, { center: this.state.center, zoom: this.state.zoom });
} else if (this.state.action === action.edit) {
this.setState({ action: action.view });
}
}
onSndBtn() {
this.setState({ action: action.edit });
}
onViewportChanged(viewport) {
this.state.center = viewport.center;
this.state.zoom = viewport.zoom;
}
handleRemove(subscriptionId) {
const { t, subscriptions } = this.props;
confirm(t('Dejarás de recibir notificaciones de fuegos en esa área ¿Estás seguro/a? '), { okBtn: t('Sí'), cancelBtn: t('No') }).then(
() => {
// `proceed` callback
const num = subscriptions.length;
Meteor.call('subscriptions.remove', subscriptionId, (error) => {
if (error) {
Bert.alert(error.reason, 'danger');
} else {
Bert.alert(t('Desuscrito'), 'success');
if (num === 1) { // it was 1, now deleted
this.setState({ action: action.view });
}
}
});
},
() => {
// `cancel` callback
}
);
}
render() {
const {
loading,
t,
subscriptions,
maxDistance
} = this.props;
const firstBtnTitle = ['Añadir zona', '', 'Terminar']; // view, add, edit
return (!loading ? (
<div className="Subscriptions">
<Helmet>
<title>{t('AppName')}: {t('Suscripciones a alertas de fuegos en zonas de mi interés')}</title>
</Helmet>
<h4 className="page-header"><Trans>Suscripciones a alertas de fuegos en zonas de mi interés</Trans></h4>
{ subscriptions.length === 0 ?
<Alert bsStyle="warning"><Trans>No estás suscrito a fuegos en ninguna zona</Trans></Alert> :
<Alert bsStyle="success"><Trans>En verde, áreas de las que recibirás alertas de fuegos</Trans></Alert>
}
{ maxDistance && maxDistance.distance > 20 &&
<Alert bsStyle="warning"><Trans>Estás subscrito a una zona muy grande</Trans></Alert>
}
<br />
<SelectionMap
center={[null, null]}
zoom={11}
action={this.state.action}
fstBtn={t(firstBtnTitle[this.state.action])}
onFstBtn={state => this.onFstBtn(state)}
sndBtn={this.state.action === action.view && this.props.subscriptions.length >= 1 ? t('Editar') : null}
onSndBtn={() => this.onSndBtn()}
onViewportChanged={viewport => this.onViewportChanged(viewport)}
loadingSubs={this.props.loading}
currentSubs={this.props.subscriptions}
onRemove={(id) => { this.handleRemove(id); }}
disableFstBtn={false}
/>
</div>
) : <Loading />);
}
}
Subscriptions.propTypes = {
loading: PropTypes.bool.isRequired,
subscriptions: PropTypes.arrayOf(PropTypes.object).isRequired,
match: PropTypes.object.isRequired,
t: PropTypes.func.isRequired,
history: PropTypes.object.isRequired,
maxDistance: PropTypes.object,
location: PropTypes.object
};
export default withTranslation()(withTracker(() => {
const subscription = Meteor.subscribe('mysubscriptions');
// console.log(UserSubsToFiresCollection.find().fetch());
return {
loading: !subscription.ready(),
subscriptions: UserSubsToFiresCollection.find({ owner: Meteor.userId() }).fetch(),
maxDistance: UserSubsToFiresCollection.findOne({ owner: Meteor.userId() }, { sort: { distance: -1 } })
};
})(Subscriptions));